diff --git a/20220331_Exkurs_DGE.pdf b/20220331_Exkurs_DGE.pdf deleted file mode 100644 index 749d936d7622b797c19253dd15b596f45ee32bdb..0000000000000000000000000000000000000000 Binary files a/20220331_Exkurs_DGE.pdf and /dev/null differ diff --git a/Exercises/.gitkeep b/Exercises/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/Exercises/Project2/.gitkeep b/Exercises/Project2/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/Exercises/Project2/AthNd1_v2c.fasta b/Exercises/Project2/AthNd1_v2c.fasta deleted file mode 100644 index a5e920e05c2017409602ce0e1f387b2e1b66ec77..0000000000000000000000000000000000000000 Binary files a/Exercises/Project2/AthNd1_v2c.fasta and /dev/null differ diff --git a/Exercises/Project2/Primer_pairs.txt b/Exercises/Project2/Primer_pairs.txt deleted file mode 100644 index 39b6933d4de21ec196dcf878c599f589ac5b7a85..0000000000000000000000000000000000000000 --- a/Exercises/Project2/Primer_pairs.txt +++ /dev/null @@ -1,65 +0,0 @@ -Name Primer1 Primer2 -M01 22 23 -M02 26 27 -M03 30 31 -M05 42 43 -M06 46 47 -M07 NT12 NT13 -M09 130 131 -M11 NT10 NT11 -M12 206 207 -M13 03_NT04 03_NT05 -M14 03_NT22 03_NT23 -M15 03_NT26 03_NT27 -M16 03_NT56 03_NT57 -M20 424 425 -M21 426 427 -M22 430 431 -M23 NT18 NT19 -M24 NT34 NT35 -M25 504 505 -M26 606 607 -M27 622 623 -M29 628 629 -M30 704 705 -M31 708 709 -M32 710 711 -M33 712 713 -M34 800 801 -M36 NT16 NT17 -M37 900 901 -M38 1000 1001 -M39 1002 1003 -M41 1020 1021 -M42 1100 1101 -M44 1122 1123 -M45 1132 1133 -M46 1204 1205 -M47 1208 1209 -M48 1210 1211 -M49 NT06 NT07 -M50 1300 1301 -M51 1400 1401 -M52 1402 1403 -M53 1404 1405 -M55 1408 1409 -M56 1410 1411 -M57 1412 1413 -M60 1602 1603 -M62 1702 1703 -M64 1706 1707 -M66 1800 1801 -M67 1902 1903 -M68 2000 2001 -M69 2002 2003 -M70 2004 2005 -M72 2300 2301 -M74 2402 2403 -M77 822 823 -M78 2334 2335 -M81 2630 2633 -M81B 2630 2631 -M82 1502 1503 -M84 114a 114b -M90 21C1 21C2 -M91 22C1 22C2 \ No newline at end of file diff --git a/Exercises/Project2/Primers.txt b/Exercises/Project2/Primers.txt deleted file mode 100644 index b1e67e1087dcae8b23b10ba22d08ed3f282e421f..0000000000000000000000000000000000000000 --- a/Exercises/Project2/Primers.txt +++ /dev/null @@ -1,171 +0,0 @@ -Name Sequence -0022 gcagatgttcgttcaaag -0023 aggctggattcccaaaac -0026 gaagctaagaccatacctg -0027 tggaaacaagagcaatgatc -0030 atctgtgcaatgttgtgg -0031 tctgcatgggagagtagg -00x1 aagttataatgctgatcattggg -0042 ctcttactacactgctgtc -0043 gagaccacatagacatgtg -00x3 ttatctgctaaaatggttgc -0046 agattagggttctcgggtc -0047 cgttactataaaaggcgaatac -00x4 tgcgtaagaactaagagtg -NT12 AACCCGAGCATTAATTCGTGC -NT13 CTCTTCCTCAAGTTGTGGCTG -00x6 ggtgccggtgacgaaaag -0130 tggacctaaagcatggtac -0131 gaacacttttgaaagacgag -01x1 ctacaccggaaaagctagtc00x1 -NT10 CACGTGGCTTGGACTAATTGG -NT11 CCAACACAGCCTTCACGTAAAG -02x4 aggattccacattaggactccac -0206 TTTCTTGTAGCCTCCTCAACC -0207 TCATTCTCATTTTCCTGAAACG -02x2 acgtcaagctcgatgcaac -NT04 TTATCCTATATTTCGAATCCGATTG -NT05 AACTAAGACTGTCTTTTGGTAAAAT -03x1 gcagacttctcgcaaacggcagacttctcgcaaacggatcccaactcgggactggaag -NT22 CGCACCGACAATTCTCTAGCC -NT23 CTGCTTTTCCCACGTCCTCTC -03x3 gatcccaactcgggactggaag -NT26 AAGGGTGTTTGGAGGGAAGTC -NT27 GTAGCAGCTTTGTAACACCGG -03x4 gatggatcattttgatggagaaacagg -NT56 GAGACGCAGGTATTTATAAACTTAT -NT57 AATCAAACTTGTGAATGAACTAGTA -03x6 actttggtaaactacgagagc -0300 AAATCTAATGTTATTGAACAAGTG -0301 CATCCAACATTACCCCAAACC -0304 ATACAAGATTCTACCTCGTCG -0305 ATCCTAAAATCGCAGCTCTTC -03x7 tctaacgactaaagacattccac -0424 ctaggcaaaatagccaaac -0425 tcactagcgaaagctcag -0426 atggatcgacaacgatgg -0427 tggtcatcccaattcaac -0430 ttgtggattctctgttatcc -0431 cggtaaattaaagcgggac -NT18 ACACAGAAAACTTCCCCAAGTC -NT19 TGTTTCTGCTTCGAGACGATC -NT34 GGATTCAAACATGTCCCGTACC -NT35 TTGTCTTCCTCACCAAACCCC -0504 AGTGGTGGAATCTACTTACGG -0505 GAAAGATTACCTTCAAGGGTG -05x1 tgatggaccagagttttgg -0606 GTTTGTATAGTGCCTTAGTGG -0607 CCACTAATGCTTGATACATCC -N304 attcactatcgttattacacaagttacctg -N305 tgtgacgaatgatgcaaaacgag -0622 tgcttgctacatgacttttg -0623 ccgaattggtaaaggacc -0628 aaagatgccacacaaacac -0629 tgctgacttccccatttac -06x2 gattcgaatgatagtaaaatgctg -0704 TGAGTGGGGGTAATTATGTTC -0705 ATCCGTTTCACATTTTGGTCG -0708 TGTGCTAGATTACGCTACATC -0709 CCTTCACCAGAAGATTCTTAC -0710 CTGAGTCAACCAGATTTGGTC -0711 CAATGTTTTCAAGCCCGATTC -0712 AAGTACTGTGCATACGTCATC -0713 ACATAAGCAGGTCTTAATCCC -0800 GTGGTGTTTGCCTGTTATGAG -0801 TTGAGGTGTATTTTGCATGTTC -08x1 tggacacctacatgtgag -0820 aggatgaggagtatacagag -0821 tggtaagtattcccgcttac -08x2 tcattacccaaacggtgc -NT16 GCTCATTTGTGTGACCCAAATG -NT17 ATATTGTTGGAGCGCTTGTGAC -0900 TAACAATCACTCACAATACATAG -0901 TCCGATTTTGGTTCAAGATGG -09x1 agcattacattatgattttaaacg -1000 TGAACTTGCGTCTTGTTCTTC -1001 TCATGGTTAAGGGATCTCTGC -1002 TTTGGTACTAGGCATTCTTGC -1003 AGATTGATACCATGAGCATGG -1020 gatgctggtctactccag -1021 tgaatgtaaacccaagtcg -10x1 acaggccctaagtatcg -1100 ACCTCTCGTTTGCTAATCCTG -1101 TTGCATCATTCTCCTGTGGTG -11x2 atggaattgcctccaatgc -1122 taaccattccagcctttc -1123 cttgttcagagagcaagc -1132 tgaagcacaaataagtcac -1133 accaaatattttcaaagttgc -1204 AGCTACTAAAGACCAATGCTC -1205 TTCCCCATTACCAATGATTCG -1208 GTCACTTTCACTCTTTCAGAG -1209 ACTTAACCGCAGCATCAATAG -1210 TGAATGTTGAATAGAGGCGAC -1211 ACTTACCAACCATAGCCATAG -NT06 TCATATACTCCATAAACTATCTCGT -NT07 TTGTAAGGGTATGAAAATTCCATTT -13x1 ccgtgggtacctataatcc -1300 TTCTCACCAAATAAGAATAGATG -1301 CGAAATTACCCTCCATGACTC -1400 TGGTGCAGGTGAGATATATTC -1401 GATACGAATTTGACCAAATTATG -14x1 gaacagcccttcacctg -1402 TCCCTATGTTCATAACTCGAC -1403 TCGAAGATGGCTTTGACCATC -1404 ATTAGCCTTCATGTTTCCTCC -1405 TATCTTCATGGCTTCTCACTC -1408 GAGATGTTTATGGAAAGCAGG -1409 CCTAAATAGTTGACTTCAGCC -1410 GGAATTGTAATCCTTCACCAG -1411 ACACGTCATGTACTAGTGTCC -1412 CATTTGCTACGATGGCTAGTC -1413 GATCAGAAGTCACGATCTTTG -1602 AACCAAGTAAAACTCAGCCTC -1603 AAGCTAATCGCTGAGTTATTAC -1702 TCGACCAGTATACTCGATCAC -1703 AGATCTCAACAGATCACTCTG -1706 ACATAATCAACACCGACCTCC -1707 AGGAAGTTGCTTGGTGATGTG -1800 TATTGATCAAGTGCAGCCATG -1801 TCAGATGGATGTACCCATTTG -1902 TGTTGTGATTTTGGGCCTGAG -1903 GAAAGGCCAATAGGCTAATGG -2000 TTTGCTAGATTTGCCTTCTCG -2001 TAGATATGCATCCAGAACAGG -2002 TTCGAGTAACCCTGTTACATC -2003 TCGTTCTTACTCTCAGCAGTG -2004 ATCGTTTTAACCACCGGTTTC -2005 ATTCAGACATAACTGGGGCAG -2300 TTGGTTATCAGTGGAACTGTG -2301 GCATCCGTTCAAGGAATTAAG -2402 ACTTCAACAGGGAGATGACAG -2403 GCACATAACAAGATGTGATCG -0822 tctgagtgttggggatag -0823 gaccgtcactaacagtagg -2334 TTGCACCTTCAAAGGCTG -2335 TGTGTACATGGCCTGTCG -2336 CACTCACCTCATCTTGGGAC -1730 CGGTACTATCTAATGAAGACAAAC -1731 CGACATCTAACAGAAATCATAAC -1732 TACTACCTAATTTACGGGAAC -1733 GACATCTAACAGAAATCATAACG -2030 CTAACCACTTATGTTCTCTTGC -2034 GACGAACATCGTCCTCTAG -2032 CTAACCACTTCTGTTCTCTTAC -2035 GGACGAACATCATCCTGTAG -2630 GGTTCTAGTTGTTACTACAAGA -2631 TCGTTGCATTTTAGTCGG -2633 TCGTTGCATTTTAGTCCG -1502 GAGCAGATACCAAAGCATTTG -1503 TATAAAGGGAGTCTCCACAGG -114a TTCACTAAGTATAGCAGCAAGG -114b CGAACCTTTTCTCCTAGCCTTC -114c GGACAGACACCAAGACAATGC -21C1 GTCGTAACATTTGGCGACTACG -21C2 AGACTGCCCGAATCTTTGGAAT -21N1 GATCAACACATGCTCCCTACCA -21N2 ATCAGTTACGAAACGACGGACA -22C1 TCCTCCACCTAAGCCATCACTA -22C2 AGAAGACGTCGTAGCTAGAGGA -22N9 TATCGGTGATCATACGGCTTGG -22N0 TGACAGTGAACTCCTGAATCCG diff --git a/Exercises/Project2/README.txt b/Exercises/Project2/README.txt deleted file mode 100644 index 345cea07984e5d34d9721bd7987cbe7621d5b803..0000000000000000000000000000000000000000 --- a/Exercises/Project2/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -Project2: in silico- PCR -Primer aus einer Datei einlesen und in Referenzseq. suchen, um die PCR-Produktgröße zu bestimmen. Auf Fehlbindungen in anderen Regionen prüfen. Primer formatiert in multiplen FASTA-Dateien ausgeben mit Tm-Wert Berechnungen. diff --git a/Exercises/Python_course_2021_exercises_A.ipynb b/Exercises/Python_course_2021_exercises_A.ipynb deleted file mode 100644 index 5860d02511e137b51a3c979f48f3cd5c91d8b740..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2021_exercises_A.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Python_course_2021_exercises_A.ipynb","provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyOtXoTh9bpM3+wk3vCpa80j"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"D9wuSivclqKR"},"source":["# Python course 2021 - Exercises A"]},{"cell_type":"markdown","metadata":{"id":"8nq-mSErlstG"},"source":["## Part1 - Variables"]},{"cell_type":"markdown","metadata":{"id":"Dc_9QuyRmFB0"},"source":["\r\n","\r\n","---\r\n","\r\n","\r\n","1.1) Save 3.14159265359 in a variable of type float!"]},{"cell_type":"code","metadata":{"id":"t0cbYO8ymZZZ"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"8GnX41irmahZ"},"source":["\r\n","\r\n","---\r\n","\r\n","1.2) Convert variable from float to integer!\r\n","\r\n","\r\n","\r\n"]},{"cell_type":"code","metadata":{"id":"IF5LB4a1mrIq"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"Wpg5yXPMmx9S"},"source":["\r\n","\r\n","---\r\n","\r\n","1.3) Convert variable back! What happens?"]},{"cell_type":"code","metadata":{"id":"MKBxedZxm4Zz"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"tadPKecSm4rq"},"source":["\r\n","\r\n","---\r\n","1.4) Convert variable type to string!\r\n"]},{"cell_type":"code","metadata":{"id":"1iqoYMyKm47q"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"wpSIghwHm5Ej"},"source":["\r\n","\r\n","---\r\n","\r\n","1.5) Save 'Python' in a string variable!"]},{"cell_type":"code","metadata":{"id":"N7XlJWFbnGAz"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"fBL218wOnGLa"},"source":["\r\n","\r\n","---\r\n","1.6) Convert variable type to float! What happens?\r\n"]},{"cell_type":"code","metadata":{"id":"jWenjrpGnLMi"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"FB_ZFKiNnLVj"},"source":["\r\n","\r\n","---\r\n","\r\n","\r\n","1.7) What is a pitfall in regards to division when working with int/float?"]},{"cell_type":"markdown","metadata":{"id":"I4ZTk_1wnVYq"},"source":["---type your answer here (double click)---"]},{"cell_type":"markdown","metadata":{"id":"O5qjeyUhniCs"},"source":["## Part2 - Functions"]},{"cell_type":"markdown","metadata":{"id":"luO5CdEcnxrz"},"source":["Primer: 'ATGCCATGCATTCGACTACG'"]},{"cell_type":"markdown","metadata":{"id":"91zd9CgHn4f8"},"source":["\r\n","\r\n","---\r\n","\r\n","\r\n","2.1) Calculate length of primer and print it!"]},{"cell_type":"code","metadata":{"id":"k3FggWgun-cW","executionInfo":{"status":"ok","timestamp":1611064497629,"user_tz":-60,"elapsed":575,"user":{"displayName":"Katharina Sielemann","photoUrl":"","userId":"00960067943696917992"}}},"source":[""],"execution_count":1,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"vilS9kFun-o6"},"source":["\r\n","\r\n","---\r\n","\r\n","2.2) Get number of 'G's and print it!"]},{"cell_type":"code","metadata":{"id":"qTtPu44JoFWb"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"RhxbY3ReoFeE"},"source":["\r\n","\r\n","---\r\n","2.3) Write a function to analyze the nucleotide composition of a primer and print it!\r\n"]},{"cell_type":"code","metadata":{"id":"hPT9ciehoNvl"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"nxYFsZTfoN5y"},"source":["\r\n","\r\n","---\r\n","2.4) Is it a suitable primer? Why (not)?\r\n"]},{"cell_type":"markdown","metadata":{"id":"YNfwCwHxoT6S"},"source":["---type your answer here (double click)---"]}]} \ No newline at end of file diff --git a/Exercises/Python_course_2021_exercises_B.ipynb b/Exercises/Python_course_2021_exercises_B.ipynb deleted file mode 100644 index bd208cdf8223afd73759530c393862b7d12c2f2f..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2021_exercises_B.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Python_course_2021_exercises_B.ipynb","provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyOECfEbqoA1+SPfgVXeDINI"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"9vv0rpCuGI-0"},"source":["# Python course 2021 - Exercises B\n","\n"]},{"cell_type":"markdown","metadata":{"id":"MmKoM-5LGKuq"},"source":["## Part1 - control structures"]},{"cell_type":"markdown","metadata":{"id":"G7FusG7CGbta"},"source":["\n","\n","---\n","1.1) Write a script for guessing numbers!\n"]},{"cell_type":"code","metadata":{"id":"scIcmdvJGjAe","executionInfo":{"status":"ok","timestamp":1647801946865,"user_tz":420,"elapsed":4,"user":{"displayName":"Katharina Sielemann","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"00960067943696917992"}}},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"0q2YJKgCGjTT"},"source":["\n","\n","---\n","1.2) Add tips (smaller/larger) during the guessing process!\n"]},{"cell_type":"code","metadata":{"id":"MATuLFxCGryV"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"69vKvpfXG1O0"},"source":["## Part2 - loops"]},{"cell_type":"markdown","metadata":{"id":"WmbSBvCGG6Fc"},"source":["\n","\n","---\n","2.1) Write a function counting to 100 and printing all numbers which can be divided by 4 without any residue!\n","\n","* Info: 10%2 #modulo division in Python\n"]},{"cell_type":"code","metadata":{"id":"N7JQLOS4HYIc"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"G3ocU6nnHYTp"},"source":["\n","\n","---\n","2.2) Write a function counting down from 1000 to 0 and printing all numbers!\n"]},{"cell_type":"code","metadata":{"id":"Zr_WTneeHgo4"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"F_k9KW4gHgwg"},"source":["\n","\n","---\n","2.3) Generate a list of species names! Write a function printing all species names starting with \"E\"!\n"]},{"cell_type":"code","metadata":{"id":"daVLjj-aHo_C"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"vC_BZDXZHpJA"},"source":["\n","\n","---\n","2.4) Expand this function to limit the printing to species names which are additionally shorter than 10 characters!\n"]},{"cell_type":"code","metadata":{"id":"BS1PycUwHydi"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"C0aWx374HykI"},"source":["\n","\n","---\n","2.5) Expand this function to limit the printing to species names which are additionally ending with \"a\".\n"]},{"cell_type":"code","metadata":{"id":"2dO2405CH8Ab"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"SL5Jk3GHIMLx"},"source":["## Part3 - range & enumerate"]},{"cell_type":"markdown","metadata":{"id":"A65Z5AeQIQrQ"},"source":["\n","\n","---\n","3.1) Write a script to print 50x \"here\" and the current value of the control variable!\n"]},{"cell_type":"code","metadata":{"id":"kwRdBZ5lIaWb"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"EXYM3E55Iaf4"},"source":["\n","\n","---\n","3.2) Write a script to walk through the species list and to print the character from the species where the index corresponds to the current control variable value!\n"]},{"cell_type":"code","metadata":{"id":"xf1tPln-Im6w"},"source":[""],"execution_count":null,"outputs":[]}]} \ No newline at end of file diff --git a/Exercises/Python_course_2021_exercises_C.ipynb b/Exercises/Python_course_2021_exercises_C.ipynb deleted file mode 100644 index c91c53ac6dd9b4c0864a97d1e524109fc1cfe2e6..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2021_exercises_C.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Python_course_2021_exercises_C.ipynb","provenance":[],"collapsed_sections":[],"mount_file_id":"10zW2TF8fCLDpT0MC2wTZpCsnqqMUSjtJ","authorship_tag":"ABX9TyPFQtWWTW3EKHHiK1/0//8f"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"FyvebZ68I8BJ"},"source":["# Python course 2021 - Exercises C"]},{"cell_type":"markdown","metadata":{"id":"8PgJ1ymVJCIO"},"source":["## Part1 - file handling"]},{"cell_type":"markdown","metadata":{"id":"Ws7tJiEXJG8f"},"source":["\n","\n","---\n","1.1) Count number of sequences (number of headers) in AtCol0_Exons.fasta!\n"]},{"cell_type":"code","metadata":{"id":"JzgmMxR0JVxL","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1617797420807,"user_tz":-120,"elapsed":547,"user":{"displayName":"Katharina Sielemann","photoUrl":"","userId":"00960067943696917992"}},"outputId":"349f565d-112d-4e47-e996-c93ce97bce81"},"source":["from google.colab import drive\n","drive.mount('/content/drive')"],"execution_count":null,"outputs":[{"output_type":"stream","text":["Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n"],"name":"stdout"}]},{"cell_type":"code","metadata":{"id":"oEJidIAEy8S5","executionInfo":{"status":"ok","timestamp":1617888058763,"user_tz":-120,"elapsed":2164,"user":{"displayName":"Katharina Sielemann","photoUrl":"","userId":"00960067943696917992"}}},"source":["datei = open(\"/content/drive/MyDrive/Python_course_2021_data/AtCol0_Exons.fasta\", \"r\")\n","lines = datei.readlines()\n","datei.close()"],"execution_count":19,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"rFtHoz5UKujx"},"source":["\n","\n","---\n","1.2) Count number of sequence lines!\n"]},{"cell_type":"code","metadata":{"id":"AgMttuZlKyBg","executionInfo":{"status":"ok","timestamp":1617888034914,"user_tz":-120,"elapsed":1728,"user":{"displayName":"Katharina Sielemann","photoUrl":"","userId":"00960067943696917992"}}},"source":[""],"execution_count":18,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"YTH3rkjJKyNm"},"source":["\n","\n","---\n","1.3) Count number of characters in document! (How many per line?)\n"]},{"cell_type":"code","metadata":{"id":"6ECkHsa9K3-X"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"I9bkusUsK4HV"},"source":["\n","\n","---\n","1.4) How long are all contained sequences combined?\n"]},{"cell_type":"code","metadata":{"id":"XC4que0hK81W"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"5NnxagAWK9AP"},"source":["\n","\n","---\n","1.5) Calculate the average sequence length in this file!\n"]},{"cell_type":"code","metadata":{"id":"MZNV3sNqLB62"},"source":[""],"execution_count":null,"outputs":[]}]} \ No newline at end of file diff --git a/Exercises/Python_course_2021_exercises_D.ipynb b/Exercises/Python_course_2021_exercises_D.ipynb deleted file mode 100644 index 4f2c94b3e70c5e5f2b820911d8d012cb8cd3b695..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2021_exercises_D.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Python_course_2021_exercises_D.ipynb","provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyNjSyvLh7SDHkiQSK3gBPn/"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"xqfYLmi0LWEl"},"source":["# Python course 2021 - Exercises D"]},{"cell_type":"markdown","metadata":{"id":"LRZcpmP8LaR_"},"source":["## Part1 - writing files"]},{"cell_type":"markdown","metadata":{"id":"NDIaKYRcLfz1"},"source":["\n","\n","---\n","1.1) Read the file AtCol0_Exons.fasta and write all headers (starting with '>') into a new file!\n","\n"]},{"cell_type":"code","metadata":{"id":"aO4lTjReLsDC"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"ddWzYDHlLsMN"},"source":["\n","\n","---\n","1.2) Read the file AtCol0_Exons.fasta and write the following:\n","* Line if it is a header\n","* Length of line if it is a sequence line\n"]},{"cell_type":"code","metadata":{"id":"HAaoquFmL4jV"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"yvanoP6kL4rn"},"source":["\n","\n","---\n","1.3) Calculate the number of sequences, the cumulative length and the average length in a new file! Are they matching the values of the original file?\n"]},{"cell_type":"code","metadata":{"id":"N5lQi7dyMEXf"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"L4KLtwRJMEgM"},"source":["\n","\n","---\n","1.4) Write sequences into a new file if their length is a multiple of 10!\n"]},{"cell_type":"code","metadata":{"id":"_87Mx4EUMKw9"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"oOKcgJ_eMTgE"},"source":["## Part2 - characters"]},{"cell_type":"markdown","metadata":{"id":"MMM8BTO3MgXN"},"source":["\n","\n","---\n","2.1) Read the file AtCol0_Exons.fasta and write the following:\n","* Only Arabidopsis Gene Identifier (e.g. AT1G01010)\n","* Gene Identifier, exon name, exon length (tab-delimited)\n","\n","\n"]},{"cell_type":"code","metadata":{"id":"oiHgx5jQMyNX"},"source":[""],"execution_count":null,"outputs":[]}]} \ No newline at end of file diff --git a/Exercises/Python_course_2021_exercises_E.ipynb b/Exercises/Python_course_2021_exercises_E.ipynb deleted file mode 100644 index 5530af2965464a13403f81f249d7294b3d5a9b5f..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2021_exercises_E.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Python_course_2021_exercises_E.ipynb","provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyN8v5be18Xq9Ti6f0gcfKxW"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"pxY28jqUNT_M"},"source":["# Python course 2021 - Exercises E"]},{"cell_type":"markdown","metadata":{"id":"WGWSyndONVE2"},"source":["## Part1 - modules"]},{"cell_type":"markdown","metadata":{"id":"a1AOuxVxNYLV"},"source":["\n","\n","---\n","1.1) Write all AGIs of AtCol0_exons.fasta into a new file!\n"]},{"cell_type":"code","metadata":{"id":"8lRQbs47Ng1h","executionInfo":{"status":"ok","timestamp":1647801820916,"user_tz":420,"elapsed":5,"user":{"displayName":"Katharina Sielemann","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"00960067943696917992"}}},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"kx5tqYs-Ng-z"},"source":["\n","\n","---\n","1.2) Some IDs occur multiple times. Add a filter step to reduce the results to unique IDs!\n"]},{"cell_type":"code","metadata":{"id":"_mh32ptqNq4a","executionInfo":{"status":"ok","timestamp":1647801820919,"user_tz":420,"elapsed":6,"user":{"displayName":"Katharina Sielemann","photoUrl":"https://lh3.googleusercontent.com/a/default-user=s64","userId":"00960067943696917992"}}},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"B03_0srPNrA8"},"source":["\n","\n","---\n","1.3) Calculate the frequency of each AGI and construct a histogram (matplotlib)!\n","```\n","plt.hist(<list_of_values>) #tip\n","```\n","\n","\n"]},{"cell_type":"code","metadata":{"id":"dx5WtRZeOFm5"},"source":[""],"execution_count":null,"outputs":[]}]} \ No newline at end of file diff --git a/Exercises/Python_course_2021_exercises_F.ipynb b/Exercises/Python_course_2021_exercises_F.ipynb deleted file mode 100644 index 056cc86170dc929823ab4d580f1de9b9de431736..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2021_exercises_F.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Python_course_2021_exercises_F.ipynb","provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyMrKbpipzB2ofTkmux8rheE"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"C6hjQZrrO1lx"},"source":["# Python course 2021 - Exercises F"]},{"cell_type":"markdown","metadata":{"id":"RoMsf4tCO3CA"},"source":["## Part1 - DNA, RNA and peptide sequences"]},{"cell_type":"markdown","metadata":{"id":"3_wMYLkSPBrx"},"source":["\r\n","\r\n","---\r\n","1.1) Write a function to get the reverse complement (upper case letters) of a DNA sequence given in upper case letters!\r\n"]},{"cell_type":"code","metadata":{"id":"Uq70MpOBPMpe"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"trElcFlcPMzg"},"source":["\r\n","\r\n","---\r\n","1.2) Write a function to convert a DNA sequence into a RNA sequence!\r\n"]},{"cell_type":"code","metadata":{"id":"ahMEGCWTPUAY"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"EOMgpzlnPUJ6"},"source":["\r\n","\r\n","---\r\n","1.3) Write a function to translate a DNA sequence into amino acids (first frame only)!\r\n","* Tip: [wiki - codon tables](https://en.wikipedia.org/wiki/DNA_and_RNA_codon_tables)\r\n"]},{"cell_type":"code","metadata":{"id":"aFVhE4KEPrM4"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"3-KHtLeePsQ4"},"source":["\r\n","\r\n","---\r\n","1.4) Write a function to translate DNA sequences in all 6 frames into peptide sequences! The longest peptide sequence per DNA sequence should be returned!\r\n"]},{"cell_type":"code","metadata":{"id":"s50AlgALP8I3","executionInfo":{"status":"ok","timestamp":1610969544596,"user_tz":-60,"elapsed":1163,"user":{"displayName":"Katharina Sielemann","photoUrl":"","userId":"00960067943696917992"}}},"source":[""],"execution_count":4,"outputs":[]}]} \ No newline at end of file diff --git a/Exercises/Python_course_2021_exercises_G.ipynb b/Exercises/Python_course_2021_exercises_G.ipynb deleted file mode 100644 index 9ae58ca592560293adfe62ac03266820f5ae982c..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2021_exercises_G.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Python_course_2021_exercises_G.ipynb","provenance":[],"authorship_tag":"ABX9TyN8UZbswpB0LFtSKu6oqjWx"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"ehDzitPJRWMi"},"source":["# Python course 2021 - Exercises G"]},{"cell_type":"markdown","metadata":{"id":"zaUOHYyFRXP9"},"source":["## Part1 - easygui"]},{"cell_type":"markdown","metadata":{"id":"poOraNGORZmI"},"source":["\r\n","\r\n","---\r\n","1.1) Write a script to handle input of primer names and sequences! All information should be saved in a multiple FASTA file.\r\n"]},{"cell_type":"code","metadata":{"id":"0PsA0s6zRiFJ"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"HSo3WWsTRiP9"},"source":["\r\n","\r\n","---\r\n","1.2) Write a script to return a matching primer sequence from a FASTA file based on a given primer name.\r\n"]},{"cell_type":"code","metadata":{"id":"cI5tRUFgRqtG"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"j04uPl8rRq0w"},"source":["\r\n","\r\n","---\r\n","1.3) Write a script to combine both functionalities: return primer sequence, if name is already present OR generate new entry if primer is novel.\r\n"]},{"cell_type":"code","metadata":{"id":"QRh4qD7JR1TG"},"source":[""],"execution_count":null,"outputs":[]}]} \ No newline at end of file diff --git a/Exercises/Python_course_2021_exercises_H.ipynb b/Exercises/Python_course_2021_exercises_H.ipynb deleted file mode 100644 index 324b1cb002bb3fa9ae420e27502b376272c996d3..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2021_exercises_H.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Python_course_2021_exercises_H.ipynb","provenance":[],"authorship_tag":"ABX9TyMzMyfKAWq1DaW4npHxSpys"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"gEQnZRGtSH_d"},"source":["# Python course 2021 - Exercises H\r\n","\r\n"]},{"cell_type":"markdown","metadata":{"id":"ghCGX9jhSLpi"},"source":["## Operon structure plot"]},{"cell_type":"markdown","metadata":{"id":"9EvJQw1DSOcV"},"source":["\r\n","\r\n","---\r\n","Construct a figure to illustrate the order and orientation of genes in the gum gene cluster in *Xanthomonas campestris* pv. campestris!\r\n","\r\n","\r\n"]},{"cell_type":"code","metadata":{"id":"Y49kR_JEScb5"},"source":[""],"execution_count":null,"outputs":[]}]} \ No newline at end of file diff --git a/Exercises/Python_course_2021_exercises_I.ipynb b/Exercises/Python_course_2021_exercises_I.ipynb deleted file mode 100644 index 017c711ecd6d54d44d7c6dda32c4638bb2eda9ea..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2021_exercises_I.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Python_course_2021_exercises_I.ipynb","provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyNqDiCX/gVj7ZfU057pegsV"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"cWpJzrYNSp7v"},"source":["# Python course 2021 - Exercises I"]},{"cell_type":"markdown","metadata":{"id":"c4DNFd2RSto8"},"source":["## analyze the unknown data"]},{"cell_type":"markdown","metadata":{"id":"bBzuedSISwsN"},"source":["\r\n","\r\n","---\r\n","Construct a suitable visualization!\r\n"]},{"cell_type":"code","metadata":{"id":"11myUcZrS0Bj"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"6ns0rUSlS0J-"},"source":["\r\n","\r\n","---\r\n","Analyze distribution and trends!\r\n"]},{"cell_type":"code","metadata":{"id":"81oWMwlkS3cv"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"AvS4hpBRS3k2"},"source":["\r\n","\r\n","---\r\n","Apply statistical test to investigate difference!\r\n"]},{"cell_type":"code","metadata":{"id":"nHMiT9HfS-uM"},"source":[""],"execution_count":null,"outputs":[]}]} \ No newline at end of file diff --git a/Exercises/Python_course_2021_exercises_J.ipynb b/Exercises/Python_course_2021_exercises_J.ipynb deleted file mode 100644 index f7318a7d2230039a8c9d25fc8e4e7ec446205489..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2021_exercises_J.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Python_course_2021_exercises_J.ipynb","provenance":[],"collapsed_sections":[],"authorship_tag":"ABX9TyM05K/IWXmf77BfxVXYR2w3"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"39_E4jqmTIhl"},"source":["# Python course 2021 - Exercises J"]},{"cell_type":"markdown","metadata":{"id":"z4s1K0mMTMfk"},"source":["## construct heatmap"]},{"cell_type":"markdown","metadata":{"id":"eSqu04bMTPPd"},"source":["\n","\n","---\n","Read data table and construct heatmap for the gene expression!\n"]},{"cell_type":"code","metadata":{"id":"Ff7BKkNOTU7O"},"source":[""],"execution_count":null,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"Y52KQmPATVFM"},"source":["\n","\n","---\n","Display functional gene annotation!\n"]},{"cell_type":"code","metadata":{"id":"blwHVBmCTaT2"},"source":[""],"execution_count":null,"outputs":[]}]} \ No newline at end of file diff --git a/Exercises/Python_course_2022_exercises_REP_1.ipynb b/Exercises/Python_course_2022_exercises_REP_1.ipynb deleted file mode 100644 index a37c2d72937c603e00c0344a0f0f4280d663d2a2..0000000000000000000000000000000000000000 --- a/Exercises/Python_course_2022_exercises_REP_1.ipynb +++ /dev/null @@ -1,189 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "Python_course_2022_exercises_REP_1.ipynb", - "provenance": [], - "collapsed_sections": [], - "authorship_tag": "ABX9TyOK+n6xTEMdtlhr0XP+1HC1" - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, - "cells": [ - { - "cell_type": "markdown", - "source": [ - "# Python course 2022 - Repetition 1" - ], - "metadata": { - "id": "rVOAyVk29PEK", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "markdown", - "source": [ - "These exercises are meant for repeating most of what you have learned in the course this far. For most of the tasks, you already have partial solutions from the other exercises. We encourage you to make use of those to review them again and maybe spot room for improvement here and there." - ], - "metadata": { - "id": "AKw7LvX5_PDx", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "markdown", - "source": [ - "1.1) Print the current time." - ], - "metadata": { - "id": "9vyeiZ6d9cuS", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "source": [], - "metadata": { - "id": "i5YYaJQd9r5R", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "1.2) Count the number of genes (not exons) in the AtCol0_Exons.fasta file. How many genes are single-exons genes?" - ], - "metadata": { - "id": "V7JwvoYf9sD7", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "source": [], - "metadata": { - "id": "6Ws6J3hI-GeJ", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "1.3) How many of the genes are located on the forward strand? How many are located on the reverse strand?" - ], - "metadata": { - "id": "AdZ6SEqJ-Gjx", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "source": [], - "metadata": { - "id": "7mBK-0Xl-RyB", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "1.4) Count the number of genes per chromosome and plot the results." - ], - "metadata": { - "id": "fatnU9Qy-R2q", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "source": [], - "metadata": { - "id": "lH2LJKhV-c85", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "1.5) Count the number of genes located on the chondrom and plastom." - ], - "metadata": { - "id": "VNpMY2li-dAh", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "source": [], - "metadata": { - "id": "ub04PoVD-zY5", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "1.6) Which of the genes may potentially include the amino acid motive \"WIP\"?" - ], - "metadata": { - "id": "fZVveOUq-zk6", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "source": [], - "metadata": { - "id": "wyInx7BA_OWC", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": null, - "outputs": [] - } - ] -} \ No newline at end of file diff --git a/Exercises/solutions/.gitkeep b/Exercises/solutions/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/Exercises/solutions/Python_course_2021_exercises_A.ipynb b/Exercises/solutions/Python_course_2021_exercises_A.ipynb deleted file mode 100644 index c5f728be60a141b989d37c34d4c1a8d1b48d6a90..0000000000000000000000000000000000000000 --- a/Exercises/solutions/Python_course_2021_exercises_A.ipynb +++ /dev/null @@ -1,650 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "Python_course_2021_exercises_A.ipynb", - "provenance": [], - "collapsed_sections": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - } - }, - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "D9wuSivclqKR" - }, - "source": [ - "# Python course 2021 - Exercises A" - ] - }, - { - "cell_type": "code", - "source": [ - "def print_type(variable):\n", - " print(variable)\n", - " print(type(variable))" - ], - "metadata": { - "id": "f1I3gDh_zTCK" - }, - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "8nq-mSErlstG" - }, - "source": [ - "## Part1 - Variables" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Dc_9QuyRmFB0" - }, - "source": [ - "\n", - "\n", - "---\n", - "\n", - "\n", - "1.1) Save 3.14159265359 in a variable of type float!" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "t0cbYO8ymZZZ", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "cfb043ee-09d0-4a94-af82-4d0e0d5182fd" - }, - "source": [ - "pi = 3.14159265359\n", - "print_type(pi)" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "3.14159265359\n", - "<class 'float'>\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "8GnX41irmahZ" - }, - "source": [ - "\n", - "\n", - "---\n", - "\n", - "1.2) Convert variable from float to integer!\n", - "\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "IF5LB4a1mrIq", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "83acbab4-9a14-46ea-b889-1ec73523ae15" - }, - "source": [ - "pi = int(pi)\n", - "print_type(pi)" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "3\n", - "<class 'int'>\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Wpg5yXPMmx9S" - }, - "source": [ - "\n", - "\n", - "---\n", - "\n", - "1.3) Convert variable back! What happens?" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "MKBxedZxm4Zz", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "83943224-bcc4-4cdf-b0b0-7086fe1ae54f" - }, - "source": [ - "pi = float(pi)\n", - "print_type(pi)" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "3.0\n", - "<class 'float'>\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "The float is rounded down to the nearest integer and the decimal places are lost." - ], - "metadata": { - "id": "R5wJukl5zBpN" - } - }, - { - "cell_type": "markdown", - "metadata": { - "id": "tadPKecSm4rq" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.4) Convert variable type to string!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "1iqoYMyKm47q", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "5dbd4edb-5961-4f5c-ee43-de37cf23f43e" - }, - "source": [ - "pi = str(pi)\n", - "print_type(pi)" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "3.0\n", - "<class 'str'>\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "wpSIghwHm5Ej" - }, - "source": [ - "\n", - "\n", - "---\n", - "\n", - "1.5) Save 'Python' in a string variable!" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "N7XlJWFbnGAz", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "4c91df02-85dc-4cf4-8bc8-c65b86159466" - }, - "source": [ - "python = \"Python\"\n", - "print_type(python)" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Python\n", - "<class 'str'>\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "fBL218wOnGLa" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.6) Convert variable type to float! What happens?\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "jWenjrpGnLMi", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 165 - }, - "outputId": "c744a4c4-97c0-4fbd-b298-76991a22152e" - }, - "source": [ - "python = float(python)" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "error", - "ename": "ValueError", - "evalue": "ignored", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m<ipython-input-13-fc22f6f198d4>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mpython\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfloat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpython\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;31mValueError\u001b[0m: could not convert string to float: 'Python'" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "FB_ZFKiNnLVj" - }, - "source": [ - "\n", - "\n", - "---\n", - "\n", - "\n", - "1.7) What is a pitfall in regards to division when working with int/float?" - ] - }, - { - "cell_type": "code", - "source": [ - "a = 3\n", - "b = 2\n", - "\n", - "print(a / b)" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "Xr1jtrtgGyk1", - "outputId": "f4b2673b-b728-4436-ce29-f214c93d194f" - }, - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "1.5\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "I4ZTk_1wnVYq" - }, - "source": [ - "You need to ensure that no integer division is performed in case you do not want to loose the decimal places. However, in Python you do not need to worry about this." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "O5qjeyUhniCs" - }, - "source": [ - "## Part2 - Functions" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "luO5CdEcnxrz" - }, - "source": [ - "Primer: 'ATGCCATGCATTCGACTACG'" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "91zd9CgHn4f8" - }, - "source": [ - "\n", - "\n", - "---\n", - "\n", - "\n", - "2.1) Calculate length of primer and print it!" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "k3FggWgun-cW", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "608304ce-982e-408a-a104-184b56e447b3" - }, - "source": [ - "primer = \"ATGCCATGCATTCGACTACG\"\n", - "print(len(primer))" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "20\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "vilS9kFun-o6" - }, - "source": [ - "\n", - "\n", - "---\n", - "\n", - "2.2) Get number of 'G's and print it!" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "qTtPu44JoFWb", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "e0bd126d-2904-459a-efc2-a917e3771a75" - }, - "source": [ - "positions = [i for i in range(len(primer)) if primer[i] == 'G']\n", - "print(positions)\n", - "print(len(positions))" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "[2, 7, 13, 19]\n", - "4\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "RhxbY3ReoFeE" - }, - "source": [ - "\n", - "\n", - "---\n", - "2.3) Write a function to analyze the nucleotide composition of a primer and print it!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "hPT9ciehoNvl", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "58c947a3-498d-4529-ff28-28628ab196c4" - }, - "source": [ - "def analyze_composition(seq):\n", - " gc_content = seq.count(\"G\") + seq.count(\"C\")\n", - " return 100 * gc_content/len(seq)\n", - "\n", - "print(\"GC content:\", round(analyze_composition(primer), 2), '%')" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "GC content: 50.0 %\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nxYFsZTfoN5y" - }, - "source": [ - "\n", - "\n", - "---\n", - "2.4) Is it a suitable primer? Why (not)?\n" - ] - }, - { - "cell_type": "code", - "source": [ - "def compute_primer_properties(primer):\n", - " length = len(primer)\n", - " print(f\"Length: {length}\")\n", - "\n", - " gc_content = primer.count(\"G\") + primer.count(\"C\")\n", - " gc_content = gc_content / length\n", - " print(f\"GC content: {gc_content * 100} %\")\n", - "\n", - " temperature = 4 * (primer.count(\"G\") + primer.count(\"C\")) + 2*(primer.count(\"A\") + primer.count(\"T\"))\n", - " print(f\"Temperature: {temperature} degrees celsius\")\n", - "\n", - " gc_clamp = (primer[-1] == \"G\" or primer[-1] == \"C\") and (primer[-2] == \"G\" or primer[-2] == \"C\")\n", - " print(f\"GC clamp: {gc_clamp}\")\n", - "\n", - "compute_primer_properties(primer)" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "46tktXhRbSgF", - "outputId": "256748b6-cdda-48a5-973b-1435aacd6d6d" - }, - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Length: 20\n", - "GC content: 50.0 %\n", - "Temperature: 60 degrees celsius\n", - "GC clamp: True\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "The primer's properties are all in a suitable range. However, to evaluate the actual suitability of the primer, its mapping uniqueness and mapping capability to the site of interest are also relevant." - ], - "metadata": { - "id": "f5SE2eaBsLEF" - } - }, - { - "cell_type": "markdown", - "source": [ - "**Additional exercises**" - ], - "metadata": { - "id": "Yapp44wzin7Z" - } - }, - { - "cell_type": "markdown", - "source": [ - "2.5) Test if the primer contains a hairpin structure." - ], - "metadata": { - "id": "OQplpGvZieNZ" - } - }, - { - "cell_type": "code", - "source": [ - "def get_reverse_complement(sequence):\n", - " bases = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C'}\n", - "\n", - " rev_comp = []\n", - " for i in range(len(sequence)-1, -1, -1):\n", - " rev_comp += [bases[sequence[i]]]\n", - "\n", - " return ''.join(rev_comp)\n", - "\n", - "\n", - "\"\"\"\n", - "Computes all exact matches between seq and other_seq\n", - "\n", - "this method is naive and can be optimized\n", - "output is a list of 4-tuples of the form\n", - "(start position in seq, start position in other_seq, length of the match, matching string)\n", - "\"\"\"\n", - "def get_common_substrings(min_length, seq, other_seq):\n", - " length_seq = len(seq)\n", - " length_other_seq = len(other_seq)\n", - " matches = []\n", - "\n", - " for i in range(length_seq):\n", - " for j in range(length_other_seq):\n", - " current_position_seq = i\n", - " current_position_other_seq = j\n", - " current_match_length = 0\n", - " while(current_position_seq < length_seq and current_position_other_seq < length_other_seq):\n", - " if seq[current_position_seq] == other_seq[current_position_other_seq]:\n", - " current_position_seq += 1\n", - " current_position_other_seq += 1\n", - " current_match_length += 1\n", - " else:\n", - " break\n", - " if current_match_length >= min_length:\n", - " matches += [(i, j, current_match_length, seq[i:i+current_match_length])]\n", - "\n", - " return matches\n", - "\n", - "\"\"\"\n", - "Tests whether a given sequence contains a hairpin structure\n", - "\n", - "min_length describes the minimum length of the stem of the hairpin\n", - "min_distance describes the minimum length of the loop of the hairpin\n", - "\"\"\"\n", - "def has_hairpin_structure(sequence, min_length, min_distance):\n", - " length_seq = len(sequence)\n", - "\n", - " upper = min_distance\n", - " lower = 0 - min_distance\n", - "\n", - " rev_comp = get_reverse_complement(sequence)\n", - " matches = get_common_substrings(min_length, sequence, rev_comp)\n", - "\n", - " for seq_position, rev_comp_position, match_length, _ in matches:\n", - " # find start position of second match in sequence from position in reverse complement\n", - " start_position_second_match = length_seq - rev_comp_position - match_length\n", - " # print(start_position_second_match)\n", - "\n", - " # end position of first match in sequence\n", - " end_position_first_match = seq_position + match_length\n", - " # print(end_position_first_match)\n", - "\n", - " # positions need to be at least min_distance apart\n", - " if end_position_first_match - start_position_second_match <= lower or end_position_first_match - start_position_second_match >= upper:\n", - " return True\n", - " \n", - " return False\n", - "\n", - "print(primer) \n", - "print(get_reverse_complement(primer))\n", - "print(get_common_substrings(3, primer, get_reverse_complement(primer)))\n", - "print(has_hairpin_structure(primer, 3, 3))" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "Bz3QGmNBkx9D", - "outputId": "43fb551d-b47b-4db0-df9d-ff993a6d85b4" - }, - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "ATGCCATGCATTCGACTACG\n", - "CGTAGTCGAATGCATGGCAT\n", - "[(0, 9, 4, 'ATGC'), (0, 13, 3, 'ATG'), (1, 10, 3, 'TGC'), (4, 12, 4, 'CATG'), (4, 17, 3, 'CAT'), (5, 9, 6, 'ATGCAT'), (5, 13, 3, 'ATG'), (6, 10, 5, 'TGCAT'), (7, 11, 4, 'GCAT'), (7, 16, 4, 'GCAT'), (8, 12, 3, 'CAT'), (8, 17, 3, 'CAT'), (11, 5, 4, 'TCGA'), (12, 6, 3, 'CGA')]\n", - "True\n" - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/Exercises/solutions/Python_course_2021_exercises_B.ipynb b/Exercises/solutions/Python_course_2021_exercises_B.ipynb deleted file mode 100644 index cb18b5ad881040cb5468a57e2846755984fee343..0000000000000000000000000000000000000000 --- a/Exercises/solutions/Python_course_2021_exercises_B.ipynb +++ /dev/null @@ -1,784 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "Python_course_2021_exercises_B.ipynb", - "provenance": [], - "collapsed_sections": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - } - }, - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "9vv0rpCuGI-0" - }, - "source": [ - "# Python course 2021 - Exercises B\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "MmKoM-5LGKuq" - }, - "source": [ - "## Part1 - control structures" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "G7FusG7CGbta" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.1) Write a script for guessing numbers!\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "0q2YJKgCGjTT" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.2) Add tips (smaller/larger) during the guessing process!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "scIcmdvJGjAe", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "2a817a7d-fd02-4f34-a81f-5b30291858b3" - }, - "source": [ - "import random\n", - "\n", - "def guessing_game(num_tries, upper_limit):\n", - " true_number = random.randrange(upper_limit)\n", - " \n", - " for i in range(num_tries):\n", - " user_input = int(input(\"Enter a number: \"))\n", - "\n", - " if (user_input == true_number):\n", - " print(\"Correct! You win the game\")\n", - " return\n", - " elif (user_input < true_number):\n", - " print(\"Too low! Guess a higher number\")\n", - " else:\n", - " print(\"Too high! Guess a lower number\")\n", - "\n", - " print(\"You are out of attempts. Better luck next time\")\n", - " print(f\"The correct number was {true_number}\")\n", - "\n", - "guessing_game(3, 10)" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Enter a number: 5\n", - "Too high! Guess a lower number\n", - "Enter a number: 2\n", - "Correct! You win the game\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "69vKvpfXG1O0" - }, - "source": [ - "## Part2 - loops" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "WmbSBvCGG6Fc" - }, - "source": [ - "\n", - "\n", - "---\n", - "2.1) Write a function counting to 100 and printing all numbers which can be divided by 4 without any residue!\n", - "\n", - "* Info: 10%2 #modulo division in Python\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "N7JQLOS4HYIc", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "7a8a1bd0-e7bd-4ea3-9da1-99354ab0b437" - }, - "source": [ - "def get_multiples_of_four(limit):\n", - " multiples = []\n", - " for i in range(0, limit, 4):\n", - " multiples += [i]\n", - " print(multiples)\n", - "\n", - "get_multiples_of_four(100)" - ], - "execution_count": 1, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "[0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96]\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "G3ocU6nnHYTp" - }, - "source": [ - "\n", - "\n", - "---\n", - "2.2) Write a function counting down from 1000 to 0 and printing all numbers!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "Zr_WTneeHgo4", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "72faa53c-7688-4bf4-bf9d-d53f9f6839d3" - }, - "source": [ - "def countdown(start):\n", - " for i in range(start, -1, -1):\n", - " print(i)\n", - "\n", - "countdown(10)" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "10\n", - "9\n", - "8\n", - "7\n", - "6\n", - "5\n", - "4\n", - "3\n", - "2\n", - "1\n", - "0\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "F_k9KW4gHgwg" - }, - "source": [ - "\n", - "\n", - "---\n", - "2.3) Generate a list of species names! Write a function printing all species names starting with \"E\"!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "daVLjj-aHo_C", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "2106843b-a1f7-4a5a-cbac-1aecc9c38e2c" - }, - "source": [ - "species = [\"D. melanogaster\", \"M. musculus\", \"E. coli\", \"C. elegans\", \"H. sapiens\", \"B. napus\", \"B. vulgaris\", \"E. multilocularis\", \"E. a\"]\n", - "\n", - "def filter_species_0(species):\n", - " filtered_species = [name for name in species if name[0] == \"E\"]\n", - " return filtered_species\n", - "\n", - "print(filter_species_0(species))" - ], - "execution_count": 3, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "['E. coli', 'E. multilocularis', 'E. a']\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "vC_BZDXZHpJA" - }, - "source": [ - "\n", - "\n", - "---\n", - "2.4) Expand this function to limit the printing to species names which are additionally shorter than 10 characters!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "BS1PycUwHydi", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "ad0a4ddc-b0a3-4c69-aea9-e6e94902df90" - }, - "source": [ - "def filter_species_1(species):\n", - " filtered_species = filter_species_0(species)\n", - " filtered_species = [name for name in filtered_species if len(name) < 10]\n", - " return filtered_species\n", - "\n", - "print(filter_species_1(species))" - ], - "execution_count": 4, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "['E. coli', 'E. a']\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "C0aWx374HykI" - }, - "source": [ - "\n", - "\n", - "---\n", - "2.5) Expand this function to limit the printing to species names which are additionally ending with \"a\".\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "2dO2405CH8Ab", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "1c026851-6fe2-4784-8cd6-d06995ad39c1" - }, - "source": [ - "def filter_species_2(species):\n", - " filtered_species = filter_species_1(species)\n", - " filtered_species = [name for name in filtered_species if name[-1] == \"a\"]\n", - " return filtered_species\n", - "\n", - "print(filter_species_2(species))" - ], - "execution_count": 5, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "['E. a']\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "**Additional exercises**" - ], - "metadata": { - "id": "Al6Bv0jlTTfG" - } - }, - { - "cell_type": "markdown", - "source": [ - "2.6) Load 4-6 protein sequences into a list and search them for specific motive, e.g. \"VAL\". You should only return those sequences that contain the motive. Additional: where does the motive lie?" - ], - "metadata": { - "id": "PSJds5r8NqmP" - } - }, - { - "cell_type": "code", - "source": [ - "\"\"\"\n", - "Protein sequences are taken from UniProt.\n", - "P01308 (insulin, H. sapiens)\n", - "P68871 (hemoglobin subunit beta, H. sapiens)\n", - "O22264 (transcription factor MYB12, A. thaliana)\n", - "P19821 (DNA polymerase I, thermostable, Thermus aquaticus)\n", - "\"\"\"\n", - "proteins = [\n", - " \"MALWMRLLPLLALLALWGPDPAAAFVNQHLCGSHLVEALYLVCGERGFFYTPKTRREAEDLQVGQVELGGGPGA\"\n", - " + \"GSLQPLALEGSLQKRGIVEQCCTSICSLYQLENYCN\",\n", - " \"MVHLTPEEKSAVTALWGKVNVDEVGGEALGRLLVVYPWTQRFFESFGDLSTPDAVMGNPKVKAHGKKVLGAFSD\"\n", - " + \"GLAHLDNLKGTFATLSELHCDKLHVDPENFRLLGNVLVCVLAHHFGKEFTPPVQAAYQKVVAGVANALAHKYH\",\n", - " \"MGRAPCCEKVGIKRGRWTAEEDQILSNYIQSNGEGSWRSLPKNAGLKRCGKSCRLRWINYLRSDLKRGNITPEE\"\n", - " + \"EELVVKLHSTLGNRWSLIAGHLPGRTDNEIKNYWNSHLSRKLHNFIRKPSISQDVSAVIMTNASSAPPPPQA\"\n", - " + \"KRRLGRTSRSAMKPKIHRTKTRKTKKTSAPPEPNADVAGADKEALMVESSGAEAELGRPCDYYGDDCNKNLM\"\n", - " + \"SINGDNGVLTFDDDIIDLLLDESDPGHLYTNTTCGGDGELHNIRDSEGARGFSDTWNQGNLDCLLQSCPSVE\"\n", - " + \"SFLNYDHQVNDASTDEFIDWDCVWQEGSDNNLWHEKENPDSMVSWLLDGDDEATIGNSNCENFGEPLDHDDE\"\n", - " + \"SALVAWLLS\",\n", - " \"MRGMLPLFEPKGRVLLVDGHHLAYRTFHALKGLTTSRGEPVQAVYGFAKSLLKALKEDGDAVIVVFDAKAPSFR\"\n", - " + \"HEAYGGYKAGRAPTPEDFPRQLALIKELVDLLGLARLEVPGYEADDVLASLAKKAEKEGYEVRILTADKDLY\"\n", - " + \"QLLSDRIHVLHPEGYLITPAWLWEKYGLRPDQWADYRALTGDESDNLPGVKGIGEKTARKLLEEWGSLEALL\"\n", - " + \"KNLDRLKPAIREKILAHMDDLKLSWDLAKVRTDLPLEVDFAKRREPDRERLRAFLERLEFGSLLHEFGLLES\"\n", - " + \"PKALEEAPWPPPEGAFVGFVLSRKEPMWADLLALAAARGGRVHRAPEPYKALRDLKEARGLLAKDLSVLALR\"\n", - " + \"EGLGLPPGDDPMLLAYLLDPSNTTPEGVARRYGGEWTEEAGERAALSERLFANLWGRLEGEERLLWLYREVE\"\n", - " + \"RPLSAVLAHMEATGVRLDVAYLRALSLEVAEEIARLEAEVFRLAGHPFNLNSRDQLERVLFDELGLPAIGKT\"\n", - " + \"EKTGKRSTSAAVLEALREAHPIVEKILQYRELTKLKSTYIDPLPDLIHPRTGRLHTRFNQTATATGRLSSSD\"\n", - " + \"PNLQNIPVRTPLGQRIRRAFIAEEGWLLVALDYSQIELRVLAHLSGDENLIRVFQEGRDIHTETASWMFGVP\"\n", - " + \"REAVDPLMRRAAKTINFGVLYGMSAHRLSQELAIPYEEAQAFIERYFQSFPKVRAWIEKTLEEGRRRGYVET\"\n", - " + \"LFGRRRYVPDLEARVKSVREAAERMAFNMPVQGTAADLMKLAMVKLFPRLEEMGARMLLQVHDELVLEAPKE\"\n", - " + \"RAEAVARLAKEVMEGVYPLAVPLEVEVGIGEDWLSAKE\"\n", - "]" - ], - "metadata": { - "id": "MYxzFmiE4ax2" - }, - "execution_count": 6, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "\"\"\"\n", - "Find the first occurrence of a motive in each protein.\n", - "If there exists an occurrence, returns the protein together with\n", - "the position of the first occurrence of the motive.\n", - "\n", - "Implemented as a generator for more flexibility.\n", - "\"\"\"\n", - "def find_motive(proteins, motive):\n", - " for protein in proteins:\n", - " # find returns the index of the first occurrence of the search string\n", - " # and -1 if no occurrence can be found\n", - " occurrence = protein.find(motive)\n", - " if occurrence > -1:\n", - " yield (occurrence, protein)\n", - "\n", - "motive = \"MA\"\n", - "for entry in find_motive(proteins, motive):\n", - " print(entry)\n" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "tM9MxtgcxxSN", - "outputId": "95b6650a-9316-4825-c7b4-76aff1c26242" - }, - "execution_count": 7, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "(0, 'MALWMRLLPLLALLALWGPDPAAAFVNQHLCGSHLVEALYLVCGERGFFYTPKTRREAEDLQVGQVELGGGPGAGSLQPLALEGSLQKRGIVEQCCTSICSLYQLENYCN')\n", - "(746, 'MRGMLPLFEPKGRVLLVDGHHLAYRTFHALKGLTTSRGEPVQAVYGFAKSLLKALKEDGDAVIVVFDAKAPSFRHEAYGGYKAGRAPTPEDFPRQLALIKELVDLLGLARLEVPGYEADDVLASLAKKAEKEGYEVRILTADKDLYQLLSDRIHVLHPEGYLITPAWLWEKYGLRPDQWADYRALTGDESDNLPGVKGIGEKTARKLLEEWGSLEALLKNLDRLKPAIREKILAHMDDLKLSWDLAKVRTDLPLEVDFAKRREPDRERLRAFLERLEFGSLLHEFGLLESPKALEEAPWPPPEGAFVGFVLSRKEPMWADLLALAAARGGRVHRAPEPYKALRDLKEARGLLAKDLSVLALREGLGLPPGDDPMLLAYLLDPSNTTPEGVARRYGGEWTEEAGERAALSERLFANLWGRLEGEERLLWLYREVERPLSAVLAHMEATGVRLDVAYLRALSLEVAEEIARLEAEVFRLAGHPFNLNSRDQLERVLFDELGLPAIGKTEKTGKRSTSAAVLEALREAHPIVEKILQYRELTKLKSTYIDPLPDLIHPRTGRLHTRFNQTATATGRLSSSDPNLQNIPVRTPLGQRIRRAFIAEEGWLLVALDYSQIELRVLAHLSGDENLIRVFQEGRDIHTETASWMFGVPREAVDPLMRRAAKTINFGVLYGMSAHRLSQELAIPYEEAQAFIERYFQSFPKVRAWIEKTLEEGRRRGYVETLFGRRRYVPDLEARVKSVREAAERMAFNMPVQGTAADLMKLAMVKLFPRLEEMGARMLLQVHDELVLEAPKERAEAVARLAKEVMEGVYPLAVPLEVEVGIGEDWLSAKE')\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "2.7) What is the amino acid composition of the proteins? Which amino acid occurs most rarely?" - ], - "metadata": { - "id": "8CO8eqBsON-S" - } - }, - { - "cell_type": "code", - "source": [ - "def get_sequence_composition(sequence):\n", - " # dictionary saving the number of observed occurrences of each character\n", - " num_occurrences = {}\n", - " for character in sequence:\n", - " # setdefault returns the value of the key if the key is already in the dictionary\n", - " # otherwise it returns the default value (here 0) and adds the (key, default) pair\n", - " # to the dictionary\n", - " num_occurrences[character] = num_occurrences.setdefault(character, 0) + 1\n", - " return num_occurrences\n", - "\n", - "def get_rarest_symbol(sequence):\n", - " num_occurrences = get_sequence_composition(sequence)\n", - " min_occurrences = len(sequence) + 1\n", - " rarest_symbol = \"\"\n", - " for symbol, occurrences in num_occurrences.items():\n", - " if occurrences < min_occurrences:\n", - " min_occurrences = occurrences\n", - " rarest_symbol = symbol\n", - " return (rarest_symbol, min_occurrences)\n", - "\n", - "print(get_sequence_composition(proteins[0]))\n", - "print(get_rarest_symbol(proteins[0]))" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "KqiT9sYX3yfW", - "outputId": "619123e6-58aa-4039-9b7e-dbd10c9bdd43" - }, - "execution_count": 8, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "{'M': 2, 'A': 10, 'L': 20, 'W': 2, 'R': 5, 'P': 6, 'G': 12, 'D': 2, 'F': 3, 'V': 6, 'N': 3, 'Q': 7, 'H': 2, 'C': 6, 'S': 5, 'E': 8, 'Y': 4, 'T': 3, 'K': 2, 'I': 2}\n", - "('M', 2)\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "SL5Jk3GHIMLx" - }, - "source": [ - "## Part3 - range & enumerate" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "A65Z5AeQIQrQ" - }, - "source": [ - "\n", - "\n", - "---\n", - "3.1) Write a script to print 50x \"here\" and the current value of the control variable!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "kwRdBZ5lIaWb", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "94195fa5-4111-4fa3-84bc-0f230a64ea0d" - }, - "source": [ - "def print_here(iterations):\n", - " for i in range(iterations):\n", - " print(i, \"here\")\n", - "\n", - "print_here(50)" - ], - "execution_count": 9, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "0 here\n", - "1 here\n", - "2 here\n", - "3 here\n", - "4 here\n", - "5 here\n", - "6 here\n", - "7 here\n", - "8 here\n", - "9 here\n", - "10 here\n", - "11 here\n", - "12 here\n", - "13 here\n", - "14 here\n", - "15 here\n", - "16 here\n", - "17 here\n", - "18 here\n", - "19 here\n", - "20 here\n", - "21 here\n", - "22 here\n", - "23 here\n", - "24 here\n", - "25 here\n", - "26 here\n", - "27 here\n", - "28 here\n", - "29 here\n", - "30 here\n", - "31 here\n", - "32 here\n", - "33 here\n", - "34 here\n", - "35 here\n", - "36 here\n", - "37 here\n", - "38 here\n", - "39 here\n", - "40 here\n", - "41 here\n", - "42 here\n", - "43 here\n", - "44 here\n", - "45 here\n", - "46 here\n", - "47 here\n", - "48 here\n", - "49 here\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "EXYM3E55Iaf4" - }, - "source": [ - "\n", - "\n", - "---\n", - "3.2) Write a script to walk through the species list and to print the character from the species where the index corresponds to the current control variable value!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "xf1tPln-Im6w", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "7d7a8a6a-0b31-47c0-bbf0-0637be30d9f3" - }, - "source": [ - "species = [\"D. melanogaster\", \"M. musculus\", \"\", \"A\", None, \"E. coli\", \"C. elegans\", \"H. sapiens\", \"B. napus\", \"B. vulgaris\", \"E. multilocularis\", \"E. a\"]\n", - "\n", - "def print_index_char(species):\n", - " for index, name in enumerate(species):\n", - " # ignore empty names and None\n", - " if name:\n", - " # if the index is larger than the largest possible index for this name\n", - " # we need to correct it by setting it to the last valid index\n", - " corrected_index = min(index, len(name) - 1)\n", - " print(index, name[corrected_index])\n", - "\n", - "# note that indices 2 and 4 are ignored because for these species name there are no characters\n", - "print_index_char(species)" - ], - "execution_count": 11, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "0 D\n", - "1 .\n", - "3 A\n", - "5 l\n", - "6 g\n", - "7 e\n", - "8 s\n", - "9 i\n", - "10 c\n", - "11 a\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "**Additional exercises**" - ], - "metadata": { - "id": "gnw2K102CI_Y" - } - }, - { - "cell_type": "markdown", - "source": [ - "3.3) Given two arbitrary sequences *x* and *y*, find a longest common substring of *x* and *y*.\n", - "Example: *x* = ACGCTA, *y* = CGCGTA yields the result CGC." - ], - "metadata": { - "id": "DTTi41OFeguO" - } - }, - { - "cell_type": "code", - "source": [ - "\"\"\"\n", - "Let x and y be two sequences over the same alphabet with lengths |x| = n, |y| = m.\n", - "\"\"\"\n", - "\n", - "\"\"\"\n", - "Finds a longest common substring of x and y naively.\n", - "\n", - "Time complexity: O(n * m^2)\n", - "Auxiliary space complexity: O(1)\n", - "\"\"\"\n", - "def longest_common_substring_naive(x, y):\n", - " length_x = len(x)\n", - " length_y = len(y)\n", - " \n", - " longest_match_length = 0\n", - " longest_match_start = 0\n", - "\n", - " for i in range(length_x):\n", - " for j in range(length_y):\n", - " current_position_x = i\n", - " current_position_y = j\n", - " current_match_length = 0\n", - " while(current_position_x < length_x and current_position_y < length_y):\n", - " if x[current_position_x] == y[current_position_y]:\n", - " current_position_x += 1\n", - " current_position_y += 1\n", - " current_match_length += 1\n", - " else:\n", - " break\n", - " if current_match_length > longest_match_length:\n", - " longest_match_length = current_match_length\n", - " longest_match_start = i\n", - "\n", - " return x[longest_match_start:longest_match_start+longest_match_length]\n", - "\n", - "\"\"\"\n", - "Find a longest common substring of x and y using dynamic programming\n", - "without any space optimizations.\n", - "Essentially we compute the longest common suffix of each combination of prefixes\n", - "of x and y. The largest of such longest common suffixes of prefixes is a\n", - "longest common substring.\n", - "The recursion formula used is\n", - "\n", - " longest_common_suffix[i-1][j-1] + 1, if x[i] = x[j]\n", - "longest_common_suffix[i][j] = \n", - " 0, otherwise\n", - "\n", - "for 1 <= i <= n, 1 <= j <= m. The recursion anchor is\n", - "\n", - "longest_common_suffix[i][0] = 0\n", - "longest_common_suffix[0][j] = 0\n", - "\n", - "for 0 <= i <= n, 0 <= j <= m.\n", - "\n", - "Time complexity: O(n * m)\n", - "Auxiliary space complexity: O(n * m)\n", - "\"\"\"\n", - "def longest_common_substring_dp(x, y):\n", - " length_x = len(x)\n", - " length_y = len(y)\n", - "\n", - " # initialize longest common suffix table\n", - " # longest_common_suffix[i][j] is the length\n", - " # of the longest common suffix of x[0:i] and y[0:j]\n", - " longest_common_suffix = [[0 for _ in range(length_y + 1)] for _ in range(length_x + 1)]\n", - "\n", - " longest_match_length = 0\n", - " longest_match_end = 0\n", - "\n", - " # compute the longest_common_suffix array row-wise\n", - " for i in range(1, length_x + 1):\n", - " for j in range(1, length_y + 1):\n", - " if (x[i-1] == y[j-1]):\n", - " longest_common_suffix[i][j] = longest_common_suffix[i-1][j-1] + 1\n", - " if longest_common_suffix[i][j] > longest_match_length:\n", - " longest_match_length = longest_common_suffix[i][j]\n", - " longest_match_end = i\n", - " else:\n", - " longest_common_suffix[i][j] = 0\n", - "\n", - " return x[longest_match_end-longest_match_length:longest_match_end]\n", - "\n", - "x = \"ACGCTA\"\n", - "x_2 = \"ACGCTAC\"\n", - "y = \"CGCGTA\"\n", - "y_2 = \"CGCGTAG\"\n", - "\n", - "print(longest_common_substring_naive(x, y))\n", - "print(longest_common_substring_dp(x,y))\n", - "print(longest_common_substring_dp(x_2, y))\n", - "print(longest_common_substring_dp(x, y_2))" - ], - "metadata": { - "id": "q3wVgvwHe0re", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "f2493e8b-eb0e-497b-95ce-86e2b832b2a1" - }, - "execution_count": 21, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "CGC\n", - "CGC\n", - "CGC\n", - "CGC\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "The auxiliary space complexity of the dynamic programming solution presented above can be optimized substantially.\n", - "\n", - "First note that the computation in that solution always only depends on the last row already computed. Therefore, it suffices to only store two rows at once decreasing the auxiliary space complexity to O(min(n,m)).\n", - "\n", - "There is still room for improvement. If you perform the computation diagonal-wise instead of row-wise, we will only need to store the last already computed element of that diagonal. This way, we can get away with O(1) auxiliary space usage.\n", - "\n", - "Another totally different solution of the longest common substring problem resolves around a data structure named generalized suffix tree. With the help of this data structure it is possibly to obtain a solution with O(n + m) time and auxiliary space complexity. However, that solution is far more difficult to implement and the relatively high constant factors in the space usage may make it prohibitive for large inputs.\n" - ], - "metadata": { - "id": "F9tF15SdxSws" - } - } - ] -} \ No newline at end of file diff --git a/Exercises/solutions/Python_course_2021_exercises_C.ipynb b/Exercises/solutions/Python_course_2021_exercises_C.ipynb deleted file mode 100644 index 0ac0325f041659b97e2d8ddcbb8fc79a4c90d5ec..0000000000000000000000000000000000000000 --- a/Exercises/solutions/Python_course_2021_exercises_C.ipynb +++ /dev/null @@ -1,338 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "Python_course_2021_exercises_C.ipynb", - "provenance": [], - "collapsed_sections": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - } - }, - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "FyvebZ68I8BJ" - }, - "source": [ - "# Python course 2021 - Exercises C" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "8PgJ1ymVJCIO" - }, - "source": [ - "## Part1 - file handling" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Ws7tJiEXJG8f" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.1) Count number of sequences (number of headers) in AtCol0_Exons.fasta!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "JzgmMxR0JVxL", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "52d24ee3-445c-4b78-9b91-52de52a9791d" - }, - "source": [ - "from google.colab import drive\n", - "drive.mount('/content/drive')" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Mounted at /content/drive\n" - ] - } - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "oEJidIAEy8S5" - }, - "source": [ - "datei = open(\"/content/drive/MyDrive/PythonProgramming/AtCol0_Exons.fasta\", \"r\")\n", - "lines = datei.readlines()\n", - "datei.close()" - ], - "execution_count": null, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "def get_num_headers(lines):\n", - " num_headers = 0\n", - " for line in lines:\n", - " if line:\n", - " if line[0] == \">\":\n", - " num_headers += 1\n", - " return num_headers\n", - "\n", - "print(get_num_headers(lines))" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "q8s7_9qRxa_b", - "outputId": "ad4a42f6-4f24-42bd-8508-0d5e92d59347" - }, - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "217183\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "rFtHoz5UKujx" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.2) Count number of sequence lines!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "AgMttuZlKyBg", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "88d9aa00-aa17-4778-e291-6d70cebfa67b" - }, - "source": [ - "def get_num_sequence_lines(lines):\n", - " num_sequence_lines = 0\n", - " for line in lines:\n", - " if line:\n", - " if line[0] != \">\":\n", - " num_sequence_lines += 1\n", - " return num_sequence_lines\n", - "\n", - "print(get_num_sequence_lines(lines))" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "916024\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "YTH3rkjJKyNm" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.3) Count number of characters in document! (How many per line?)\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "6ECkHsa9K3-X", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "fe3ccf0a-8afa-4b7f-ba19-e3870430989f" - }, - "source": [ - "def get_num_characters(lines):\n", - " num_characters = 0\n", - " num_lines = 0\n", - " for line in lines:\n", - " num_characters += len(line)\n", - " num_lines += 1\n", - " return (num_characters, num_characters / num_lines)\n", - "\n", - "print(get_num_characters(lines))" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "(81803755, 72.18783064347467)\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "I9bkusUsK4HV" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.4) How long are all contained sequences combined?\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "XC4que0hK81W", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "e77692ed-7a33-47ef-d8ee-5ac9550535fe" - }, - "source": [ - "def get_sequence_length(lines):\n", - " total_sequence_length = 0\n", - " for line in lines:\n", - " if line:\n", - " if line[0] != \">\":\n", - " line = line.strip()\n", - " total_sequence_length += len(line)\n", - " return total_sequence_length\n", - "\n", - "print(get_sequence_length(lines))" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "64867051\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "5NnxagAWK9AP" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.5) Calculate the average sequence length in this file!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "MZNV3sNqLB62", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "01b885d6-dc65-4b5d-f893-288015678122" - }, - "source": [ - "def get_average_sequence_length(lines):\n", - " return get_sequence_length(lines) / get_num_headers(lines)\n", - "\n", - "print(get_average_sequence_length(lines))" - ], - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "298.67462462531597\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "**Additional exercises**" - ], - "metadata": { - "id": "n9rZsJ5_4hTJ" - } - }, - { - "cell_type": "markdown", - "source": [ - "1.6) Parse the fasta file entry-wise. An entry consists of a header and the corresponding sequence (which may comprise multiple lines). The result should be a list of tuples of the form (header, sequence)." - ], - "metadata": { - "id": "ItrnPkVE5fsv" - } - }, - { - "cell_type": "code", - "source": [ - "\"\"\"\n", - "Parse a fasta file entry-wise as a list of tuples of the form (header, sequence).\n", - "\"\"\"\n", - "def read_fasta(file):\n", - " result = []\n", - "\n", - " header = None\n", - " sequence = []\n", - " for line in file:\n", - " # remove all whitespace from the ends\n", - " line = line.strip()\n", - " if line.startswith('>'):\n", - " # if you find a header return the previous FASTA block in tuple form after\n", - " # concatenating the sequence lines(if there is a previous block)\n", - " if header:\n", - " result += [(header, ''.join(sequence))]\n", - "\n", - " header = line\n", - " sequence = []\n", - " else:\n", - " # current line is not a header\n", - " # add line to the list of sequence lines of the current FASTA block after removing all whitespace from it\n", - " sequence.append(line.translate(str.maketrans('', '', whitespace)))\n", - " \n", - " if header:\n", - " result += [(header, ''.join(sequence))]\n", - " return result" - ], - "metadata": { - "id": "RvF09FlO6YeT" - }, - "execution_count": null, - "outputs": [] - } - ] -} \ No newline at end of file diff --git a/Exercises/solutions/Python_course_2021_exercises_D.ipynb b/Exercises/solutions/Python_course_2021_exercises_D.ipynb deleted file mode 100644 index 8f869b6e53effaaa2c06d5aa5f7346eacd7f9cc2..0000000000000000000000000000000000000000 --- a/Exercises/solutions/Python_course_2021_exercises_D.ipynb +++ /dev/null @@ -1,301 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "Python_course_2021_exercises_D.ipynb", - "provenance": [], - "collapsed_sections": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - } - }, - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "xqfYLmi0LWEl", - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "# Python course 2021 - Exercises D" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "LRZcpmP8LaR_", - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "## Part1 - writing files" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "NDIaKYRcLfz1", - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "\n", - "\n", - "---\n", - "1.1) Read the file AtCol0_Exons.fasta and write all headers (starting with '>') into a new file!\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Mounted at /content/drive\n" - ] - } - ], - "source": [ - "from google.colab import drive\n", - "drive.mount('/content/drive')\n", - "\n", - "with open(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/AtCol0_Exons.fasta\", 'r') as exons:\n", - " with open(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/Header_AtCol0_Exons.txt\", 'w') as new_file:\n", - " line = exons.readline()\n", - " while line:\n", - " if line[0] == '>':\n", - " new_file.write(line)\n", - " line = exons.readline()" - ], - "metadata": { - "pycharm": { - "name": "#%%\n" - }, - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "9OMVwvZLzW9A", - "outputId": "36f854a7-f0f2-4472-f3e5-081fad69ebe9" - } - }, - { - "cell_type": "markdown", - "source": [ - "\n", - "\n", - "---\n", - "1.2) Read the file AtCol0_Exons.fasta and write the following:\n", - "* Line if it is a header\n", - "* Length of line if it is a sequence line\n" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% md\n" - }, - "id": "4S2i2BAjzW9B" - } - }, - { - "cell_type": "code", - "execution_count": 2, - "outputs": [], - "source": [ - "with open(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/AtCol0_Exons.fasta\", 'r') as exons:\n", - " with open(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/Summary_AtCol0_Exons.txt\", 'w') as new_file:\n", - " line = exons.readline()\n", - " while line:\n", - " if line[0] == '>':\n", - " new_file.write(line)\n", - " else:\n", - " new_file.write(str(len(line.strip())) + \"\\n\")\n", - " line = exons.readline()" - ], - "metadata": { - "pycharm": { - "name": "#%%\n" - }, - "id": "WRHfLJuJzW9C" - } - }, - { - "cell_type": "markdown", - "source": [ - "\n", - "\n", - "---\n", - "1.3) Calculate the number of sequences, the cumulative length and the average length in a new file! Are they matching the values of the original file?\n" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% md\n" - }, - "id": "2Uy9-PtVzW9C" - } - }, - { - "cell_type": "code", - "execution_count": 3, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Number of sequences: 217183\n", - "Cumulative length: 64867051 bases\n", - "Average sequence length: 298.67462462531597 bases\n" - ] - } - ], - "source": [ - "def summarize_seq_info(summary_file):\n", - " with open(summary_file, 'r') as summary:\n", - " seq_count = 0\n", - " cum_len = 0\n", - " line = summary.readline()\n", - " while line:\n", - " if line[0] == '>':\n", - " seq_count += 1\n", - " else:\n", - " cum_len += int(line.strip())\n", - " line = summary.readline()\n", - " print(\"Number of sequences:\", seq_count)\n", - " print(\"Cumulative length:\", cum_len, \"bases\")\n", - " print(\"Average sequence length:\", cum_len / seq_count, \"bases\")\n", - "\n", - "summarize_seq_info(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/Summary_AtCol0_Exons.txt\")" - ], - "metadata": { - "pycharm": { - "name": "#%%\n" - }, - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "V5s-M0dSzW9D", - "outputId": "212fadb1-dbbc-4929-e53e-d41426830418" - } - }, - { - "cell_type": "markdown", - "source": [ - "\n", - "\n", - "---\n", - "1.4) Write sequences into a new file if their length is a multiple of 10!\n" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% md\n" - }, - "id": "KuS83FpyzW9E" - } - }, - { - "cell_type": "code", - "execution_count": 4, - "outputs": [], - "source": [ - "def seq_lens_multiple_of_10(fasta_file):\n", - " with open(fasta_file, 'r') as fasta_input:\n", - " with open(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/AtCol0_mult10.txt\", 'w') as out:\n", - " cum_len = 0\n", - " sequence = \"\"\n", - " line = fasta_input.readline()\n", - " while line:\n", - " if line[0] == '>': # Reading the next header\n", - " if cum_len % 10 == 0: # Check if the length is a multiple of 10\n", - " out.write(sequence + '\\n')\n", - " cum_len = 0 # Reset the sequence length and the sequence as we are in the next sequence now\n", - " sequence = \"\"\n", - " else:\n", - " sequence += line.strip() # Append the sequence to the current one as long as no other header is in between\n", - " cum_len += len(line.strip()) # Update the cumulative length for this sequence\n", - " line = fasta_input.readline()\n", - "\n", - "seq_lens_multiple_of_10(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/AtCol0_Exons.fasta\")" - ], - "metadata": { - "pycharm": { - "name": "#%%\n" - }, - "id": "m2FZHcpmzW9G" - } - }, - { - "cell_type": "markdown", - "source": [ - "## Part2 - characters" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% md\n" - }, - "id": "HAzJAcOAzW9I" - } - }, - { - "cell_type": "markdown", - "source": [ - "\n", - "\n", - "---\n", - "2.1) Read the file AtCol0_Exons.fasta and write the following:\n", - "* Only Arabidopsis Gene Identifier (e.g. AT1G01010)\n", - "* Gene Identifier, exon name, exon length (tab-delimited)\n", - "\n", - "\n" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% md\n" - }, - "id": "hUOOeTCUzW9I" - } - }, - { - "cell_type": "code", - "execution_count": 11, - "outputs": [], - "source": [ - "import re\n", - "\n", - "def arabidopsis_only(fasta_file):\n", - " with open(fasta_file, 'r') as summary:\n", - " with open(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/Arabidopsis_Exons.txt\", 'w') as arabidopsis:\n", - " line = summary.readline()\n", - " while line:\n", - " if line.startswith('>AT'):\n", - " columns = line.split('|')\n", - " gene_identifier = columns[0].strip('>').split('.')[0]\n", - " if gene_identifier in re.findall(\"AT\\dG\\d{5}\", gene_identifier):\n", - " exon_name = columns[1].strip()\n", - " exon_length = columns[3].strip().split(' ')[2]\n", - " arabidopsis.write(gene_identifier + '\\t' + exon_name + '\\t' + exon_length + '\\n')\n", - " line = summary.readline()\n", - "\n", - "arabidopsis_only(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/AtCol0_Exons.fasta\")" - ], - "metadata": { - "pycharm": { - "name": "#%%\n" - }, - "id": "YStsUutUzW9I" - } - } - ] -} \ No newline at end of file diff --git a/Exercises/solutions/Python_course_2021_exercises_E.ipynb b/Exercises/solutions/Python_course_2021_exercises_E.ipynb deleted file mode 100644 index 7145d4bf107987cdaf5c5c756fdbc9593476c22f..0000000000000000000000000000000000000000 --- a/Exercises/solutions/Python_course_2021_exercises_E.ipynb +++ /dev/null @@ -1,323 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "Python_course_2021_exercises_E.ipynb", - "provenance": [], - "collapsed_sections": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - } - }, - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "pxY28jqUNT_M" - }, - "source": [ - "# Python course 2021 - Exercises E" - ] - }, - { - "cell_type": "code", - "source": [ - "from google.colab import drive\n", - "drive.mount('/content/drive')" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "ypH9P41xJWAr", - "outputId": "cb2ede48-f81b-4b7c-b81d-b38c7988d9d6" - }, - "execution_count": 1, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "WGWSyndONVE2" - }, - "source": [ - "## Part1 - modules" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "a1AOuxVxNYLV" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.1) Write all AGIs of AtCol0_exons.fasta into a new file!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "8lRQbs47Ng1h", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "af743d2f-80f6-48a6-e6c0-238919597757" - }, - "source": [ - "def get_gene_identifiers(input, output):\n", - " with open(input, 'r') as input_file:\n", - " with open(output, 'w') as output_file:\n", - " for line in input_file:\n", - " if line.startswith(\">\"):\n", - " identifier = line[1:].split(\".\")[0]\n", - " output_file.write(identifier + \"\\n\")\n", - "\n", - "input = \"/content/drive/MyDrive/PythonProgramming/AtCol0_Exons.fasta\"\n", - "output = \"/content/drive/MyDrive/PythonProgramming/AtCol0_gene_identifiers.txt\"\n", - "get_gene_identifiers(input, output)\n", - "\n", - "def get_num_lines(input):\n", - " num_lines = 0\n", - " with open(input, 'r') as input_file:\n", - " for line in input_file:\n", - " num_lines += 1\n", - " return num_lines\n", - "\n", - "print(get_num_lines(\"/content/drive/MyDrive/PythonProgramming/AtCol0_gene_identifiers.txt\"))" - ], - "execution_count": 2, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "217183\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "kx5tqYs-Ng-z" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.2) Some IDs occur multiple times. Add a filter step to reduce the results to unique IDs!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "_mh32ptqNq4a", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "9cf72b66-496e-4611-aa29-e158a56f9ef6" - }, - "source": [ - "def get_unique_gene_identifiers(input, output):\n", - " # use the built-in set data structure\n", - " identifier_set = set()\n", - " with open(input, 'r') as input_file:\n", - " for line in input_file:\n", - " if line.startswith(\">\"):\n", - " identifier = line[1:].split(\".\")[0]\n", - " identifier_set.add(identifier)\n", - " \n", - " with open(output, 'w') as output_file:\n", - " for identifier in identifier_set:\n", - " output_file.write(identifier + \"\\n\")\n", - "\n", - "output = \"/content/drive/MyDrive/PythonProgramming/AtCol0_unique_gene_identifiers.txt\"\n", - "get_unique_gene_identifiers(input, output)\n", - "\n", - "get_num_lines(\"/content/drive/MyDrive/PythonProgramming/AtCol0_unique_gene_identifiers.txt\")" - ], - "execution_count": 3, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "33602" - ] - }, - "metadata": {}, - "execution_count": 3 - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "B03_0srPNrA8" - }, - "source": [ - "\n", - "\n", - "---\n", - "1.3) Calculate the frequency of each AGI and construct a histogram (matplotlib)!\n", - "```\n", - "plt.hist(<list_of_values>) #tip\n", - "```\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "dx5WtRZeOFm5", - "colab": { - "base_uri": "https://localhost:8080/", - "height": 840 - }, - "outputId": "86c8b671-0abf-4291-e975-4f4238b0fc65" - }, - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "def get_identifier_frequencies(input):\n", - " # use a dictionary to keep track of the number of occurrences of each identifier\n", - " identifier_occurrences = {}\n", - " with open(input, 'r') as input_file:\n", - " for line in input_file:\n", - " if line.startswith(\">\"):\n", - " identifier = line[1:].split(\".\")[0]\n", - " identifier_occurrences[identifier] = identifier_occurrences.setdefault(identifier, 0) + 1\n", - " return identifier_occurrences\n", - "\n", - "def plot_frequency_histogram(input, output):\n", - " identifier_occurrences = get_identifier_frequencies(input)\n", - " \n", - " fig, ax = plt.subplots(constrained_layout=True, dpi=200)\n", - " ax.hist(identifier_occurrences.values(), bins=range(max(identifier_occurrences.values()) + 1))\n", - " ax.set_xlabel(\"Number of occurrences\")\n", - " ax.set_ylabel(\"Number of unique identifiers\")\n", - " ax.set_title(\"AGI frequency histogram\")\n", - "\n", - " fig.savefig(output)\n", - "\n", - "plot_frequency_histogram(input, \"/content/drive/MyDrive/PythonProgramming/AtCol0_identifier_frequency_histogram.png\")" - ], - "execution_count": 4, - "outputs": [ - { - "output_type": "display_data", - "data": { - "text/plain": [ - "<Figure size 1200x800 with 1 Axes>" - ], - "image/png": "iVBORw0KGgoAAAANSUhEUgAABMcAAAM3CAYAAAA5pjfAAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAewgAAHsIBbtB1PgAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOzdedx15bz48c+3nkYNpGikgQiZGikpwyGhUIZDigzHqRwODo4pHY6h8/Pj5DiHkggpfg1KGUIh0qBDJGl49JRKCc3j8/39cV27ez27Pd33s+9930/r83691mtda61rfde197P3rf11DZGZSJIkSZIkSW203Fw3QJIkSZIkSZorJsckSZIkSZLUWibHJEmSJEmS1FomxyRJkiRJktRaJsckSZIkSZLUWibHJEmSJEmS1FomxyRJkiRJktRaJsckSZIkSZLUWibHJEmSJEmS1FomxyRJkiRJktRaJsckSZIkSZLUWibHJEmSJEmS1FomxyRJkiRJktRaJsckSZIkSZLUWibHJEmSJEmS1FomxyRJkiRJktRaJsckSZIkSZLUWibHJEmSJEmS1FomxyRJkiRJktRaJsckSdK8EhHPjohjI+IPEXFbRGTdFs5126RBIuKgxuf1oDHF3LkR8/RxxJQkSUsyOSZJ0jwSEV9u/BDOiHjnGGJG/YH9oYg4IyIujYi/RsSdEXF9RFwcEcdFxHsj4skjxjyy0cYjl7aNjbgfAb4L7AU8DFh5XLElSZKkXhbMdQMkSVIREasDL+o6vQ/wsaWI+VLg/cBj+1R5cN0eWZ/9bxFxGfB/gcMy846ZPnu6ImIH4F2NU78Bzgf+Vo//PKm2SG1UE9371MPXZOaRc9caSZImx+SYJEnzx17Aql3ntoiIbTLznOkEiohVgM8Dr+i6dCtwDnANJen0QOAhwFbA6rXOpsChwLOB3afz3KW0d6P8eeD1mZkTfL4kSZJayOSYJEnzxz6N8m3AKo3zIyfHImJF4HvADo3TZwMHA9/LzDt73LMA2B7YD/h7YEXgAdNp/Bg0h3R+wcSYBJl5OhBz3Q5Jku7PnHNMkqR5ICI2AZ5WDxN4e+PyK2rCa1T/yZKJsQ9n5naZ+a1eiTGAzLw7M3+Sma8BNgGOm8bzxuVBjfLVc/B8SZIktZDJMUmS5odXM9U75Azgc8B19Xgt4PmjBImIpwNvbJz6VGa+dzoNycw/ZuZLgH+Zzn1jsEKjvHjCz5YkSVJLmRyTJGmORURQkmMdR2Xm3cDXGuf2YTT/2ihfzpIT3E9LZv5ipveOKiJO76x6CTy8cenyrlU7MyI27nVfROxcz60XEf8aEWdHxDURcU9E/LXPc1eIiL0j4tiIuCwiboqIWyLi8og4OiJeVP9dRn0da0bEuyPinIj4S0TcHBG/i4jDImKrRr17X0+fOBs36iwc8dkLe71HA+o/ICLeFBEnRcQfIuLW+vp/HxFHRMQzRoixb6/VSuv7dlJEXBERd0TEnyLiuxHxqum8nzXWphFxUET8KCKuiojba1svi4gTIuLAiHhI1z0nNtr17mk864ON+8baazIiFkTEqyPitPo67oiIq+trGJr0jrLSbKdtpw+p++iI+HhEnBVlJdo76/v2p4g4LyK+EBH7RMSDuu5bWD+Tzb8zX+jxHcyIOGjA8x8eEQfX519bn39tPf5gRGw07PV2xXtQlFV0z+36Xh0eEds06g38XvWrExFPiIhPRcSvI+KGev2EHvduVb/fJ9fP382N1/bTiPhwRDxsxNd0n+9rRDwiIg6p7fhbRNwWEb+M8vesex5KIuJREfHpiLggIm6MsvrwWRGxf0QsP0o7JEldMtPNzc3Nzc1tDjfKcMqs223AGvX8No3zdwLrDImzSaN+Au+YxTYf2XjOkUsR5/SuNg/aNu5z386UhQNu6HHPX3s8c2fgkhGe9zNggxFew47AVQPi3AO8v9a993yfWBs36iwc8T1c2Os96lN3L8qQ1WGv/SRgzQFx9m3++wNrAicOiXkqsMoIr2cl4NPAXSO0805g9ca9z29cu3jE92854A+N+563FJ/ngxpxDgI2AM4c8hqOAJYbEHPnRt3Thzz77hHeswS+POAzNGw7qM/z30P5+zXo3tuAd474Xu5CWThk0PfqA6N8r3rVGfB+ndB139kjvi93Av8y3e8r8CrglgFxfwE8qHH/e+tr71f/h8CqM/0Mu7m5ubV1c0J+SZLm3j6N8omZeSNAZp4TERcBj6YMOfx74FMD4uzcdXzMOBs5S44Hfl3Lr2ZqxcwvATd11b2xT4ynUn7orgD8GfgRcD1lFc4nNStGxF7AV5gawnkbcBblB+tiYHPgKZRFi7YHfhZltdBrez04Sq+wU4HVGqfPBS6gLGqwPbAZ8MGI+Euf9k9ERLwV+D9MDd+9kZIAvBJYHngssHW9/nzg9IjYITNvHRJ6AfD/gGdSEgQ/BS4FVqYkfjs9ap4LfAJ404A2rgZ8l/Jv0HErJcG0qLZtA8rqqg+m/Ds2e8qcWuttBDwyInbKzB8Naf+zG228Evj2kPqjWq3Gelx9DT+ubVudkvjp9Hp7DfA74GMzfVBE/BPwgcap6ymf604idC3K35EtWPL96vgi5f18Zq0H8H3goh51z+7x/E8D+zdO3UxJ0lwDrEt5vatRPhMfjYh1M/OtA17P9sDJTK3em5RFSX5D+V5tCzwSOCgiru8XZ0D8dzD1fl1aX9OtlGTVXV3VO5+NO+rzL6Gs9BvAesB2wNqUz+LHIoLM/PiITdmVkgheDvh9bcftwOMp/+cIlL9hXwOeU3tD/ls9/yvgl5QE37aU7y+U/x34BPAPI7ZBkgTMeXbOzc3Nzc2tzRtlRcq/MfX/+u/Wdf1fG9d+MSTWEY26V89yu49sPOvIMcVc2Ii58ZC6pzfq3kVJbL0XWKGr3kqN8mMpP4Cz1j8EeGCP2JtSEhmd+Kf0acOKwIWNelcAT+lR79WUH7x3NOpmn5gbN+osHNf7Rkl6dHqb3AG8kx69S4AnUhIAnXif6RNv30ad2zvvE1097SiJs0MadRcP+relJAE6de8G3g88oEe95SgJlxPo6uHGkr23vjjC+3dso/7BS/kZbj67874cCazVVW9V4KuNujf1ep217s6Neqf3uL6AMj9hp867ur8HjbprUZJxPXs4seT3et8RX/NLm59r4AvU3q+NOmsAR3XVe3GfeCsDFzfqXQZs0+e5tzTe577fq1q/+ey7gL8Ce/Sot1LX8WeA59Gn1yMl2bgvJSHY6UG2yYjf19spSeo9e9R7GUv2bHtLPb4KeHqP+v/cqHsPQ/6Gurm5ubktuc15A9zc3Nzc3Nq8UXqDdX7Q/AlY0HX94ZSEQqfOlgNindao94NZbnfzR/SRY4rZ/NG48ZC6p3f92H3PCPG/36j/1iF1H8CSSaLtetR5feP6bcCjB8R7ZVd7s0+9jRt1Fo7jfaMkkprJhhcNibcuU8PZ7gQ27FFn367X86Puz26jbrDk0LSew+qAZ3XFfPkMP0cbMZUIvIWuRE1X3QczlbQcmLgb8dkHdb2Grw6ouzIlodqp+7I+9XZu1Dm9x/XHNa7/ZCnb3/xe7ztC/eUoyavOPccCMeBzcEKj7iX0GE5K6fHUqXMLsNmA579olO9Vrdusdw+w09K8Vz3iv6wR/2MD6jW/r4uBZw2oe1hXu28FthhQ/3uNukOHeLq5ubm5TW1OyC9J0tzap1E+OstE/PfKzD9QEg+96ndbq1HuORF9U0Q8sk7qPGjbbqRXMbf+yJAhaRHxBKAz0fz5wCcH1c/MW5gavgQludXtdY3yoZnZawhaJ95XKMMN58ILKEPQoMyndPygypl5DVPvzwqUHjrDvKX7s9uIl5TeRB3b9onxtkb5mMz8Wp96A2XmIqaGRq4KvGJA9b0pPQABTsvMhTN5Zh93Unrz9JSZtwNHN071e1+GWaNRvq5vrdnxd5S5DqG83jfXf+/7qOf3Z2rY4maUIa3d9muUP5mZl/Z7eP0s/3C6jQa+kcOH2047JqX3GJRE7yi+mZmnDbh+dNfxZzPztyPWn+nnSZJayTnHJEmaIxGxAUv+iDqqT9UvAU+v5VdGxDsz854e9VZvlG8ZoQkbsOQ8Qb2cC/x8hFhz6Rv9EjMNz2uUj+73A77LDxrlHZsXImJ1yvxcHV8aId4XKfOjTVrztX91xHu6X/snBtS9LIevbHp+o7xx98WIWIkl58w7dEi8YT7H1OveD/hsn3rNRMzhS/nMbj+picZBBr4vI1rUKO8SEZtn5sUzjDVdzZVNTxn2ejPzqoj4NiVhC2Vo7Hc61+v36smNW748Qhu+XONMx4wSrxHxeMocYBtTkpIrdVXp/F3ZMiKWy8zFQ0J+Y8j1C6ZZ/9eN8iZ9a0mS7sPkmCRJc+dVcG8v7osy89w+9b4B/BdlGNa6wHMo8zt1a05g/4BxNXIZcN4IdZoTvO8SEQ8f4Z5olDfquvZ4pv7tbqIMwRzmZyPUmQ3N1/6SiHh635pT1myUu197t+4f8L38uVFeo8f1J1I+31CGji1tQvZkSo/C9YFtImLLzFyinRGxLWVIIpQJ7E9Yymd2G8f7MlRmLoqIsyiLP6wJnBcRR1EWuzgzhy+osDSaC16M2jPyTKaSY0/uutb8Xt1I7wUBus3kszLK34x7RcQ+lPkfNx/xlhUo/xbDFuH49ZDr3fcP+ztzQ6M8o8+TJLWVyTFJkuZOc4hkv15jZOaNEXEiZU6bzn29kmPNH0YPHPbwzDydJRNAAETEQspcZ8uKUYaSrd8o7zqDZzyo63idRnnRiD3RrpjBc8eh+dpf1rdWf92vvdvfRojRXAFwhR7XH9ooLxqhJ+BAmXlPRBxBWaQBSg+xt3RVa/YaOyoz71yaZ/YwjvdlVPtRevs9lLIq5JvqdndE/C9laPZ3gO/36XU6U83vwR9GvGdho7z2gHhXjvi9unLE5zaNNPw0IgL4PGURg+laneHJsYGfkcy8uzRhtPqUCfs7lubzJEmt45xjkiTNgYjYBtiiHibwlSG3NJNnL4yIXsmv5o/TLXpcv7+6bYQ6aw6vMtDyXcerNcqj9swZZajrbFja1z7s/0wdJYExTHNI8M19a03P4ZQJzwFeFRGducWIiFWBl3fVHbdxvC+jPSjzQuAJlOGozQTKAsrw33+mJMf+EBGvu2+EGWt+D0b9fDfrrd51bSbfq2l/XjJzlL8ZUBbdaCbGvk35Pye2pCSNV8rM6Gws+Td4lN9Z0/qMjJgslCTNgMkxSZLmRrPXWAALIyL7bZRhYh0r07sH0I8b5XUj4mGz0O5lVfMH+YubP2hH3briNX+QrzpiG2ZrqOuw/55rvvYnz+C1bzxL7W5qDglerW+taaiLWXyvHj4Y2KNxeS+mhp39rCaXlmmZeW1mvpnSe2xn4H3AqZThiR0bAIdFxH+O6bHN78Gon+9mvZu6rs2n7xXA2xvlD2Tmrpn5pcz8dWb+tUdvw+5knyRpGWFyTJKkCas9WAatoDeKXqtWnt51/PIeddrq2kZ53THEaw7L2jC6xj71MWzuLlhymN2o018M6xk27tc+G5pt3CgixjX1x+ca5f36lGej19icycw7MvOMzPxQZj6PMnRxV+AnjWoH1t6rS6v5PRg1Gb9xo3x917Xm8QYjxttwxHrTEhEbMbXK61+BjwypvwbDhyBLkuYpk2OSJE3e84G1avluyoTSo2znNGI8JSKWmBw6MxfSWPkN+IeIWBnBkpN27zCGeL9iasjeGsBjRrjnKcOrLNHL50HDkm61d+CwibfH/dpnw/8Ct9fyqsB2Y4r7TaCzguKzIuJh9XvztHruZuDYMT1rXsrMuzLz25SVcZsTwL+gV/Vphm+utjnqSqzNet2rnDa/V2tGxKNHiLftiM+druZcfRdl5l19axY70mMOR0nSssHkmCRJk9fs9XVqZm4/4rYtS/64fXWP2M3eDZsAH52NF7AMag5LfXFEPLRvzRFk5k1Ac3XRvUe4rde/V6+4nYUVVmX46ngvHeG5zdf+2vmYMM3MO4AfNk4dMKa4dwNfqIfLUeaPem2jytcyc1xznM1r9T3+buNUr+/A7Y3yKBO6/6BRfl5EPGRQ5YhYnyUXxGjeT2beyJIJt1eO0IZXjVBnJhY3yqMM8XzTLLVDkjQBJsckSZqgiFiHJX8cfnmaIZr19+7uWZSZZwD/0zj1TxHxb9N8xv1OZp7N1LDTVYCjmhO0DxIRK0ZEr+FSzeF4b+7uydcV4+WUniWjaPb02ndAzA2Bd48Q7/8Bl9TyesBnRhwGSkSsFhGzOadT0yca5ZfX92wcDmeqR9RrWDI5vcwPqYyIB0XEqP9N3xza+6ce1//cKI8yrPG7wOW1vBLwyX4V62fuUKaSbpcCp/WoekSj/JaI2GRAzBcCzxyhnTNxOVOfm8dFxKYD2vEySo9gSdIyyuSYJEmT9fdM/Ti8CThpmvcfzdQPtocBu/So80/AmY3j90bEWRGx26CEUERsERH/wyzN4TMPHMjUhN/PBn4UEX2H70XE5hHxPmAhvYcjfgn4XS2vAnyvV7yIeCWl91L35N39fLVR/ueIeEmPmNsDZ1DmOBoYNzPvofRquaeeeg3wrYjou6JpRDwxIj4GLKL0QJx1mXka8PXGqS9HxPvrypLd7VsuInaJiOMjYuCca5l5GfD9evhwpuZduyAzf977rmXK7sDFEfH2iNi4V4WIWCkiDgD2bJw+tUfVZs/U3YclkDNzMfCuxqlXRMRhEbHEogoRsTrlO/Dixul/qfd3+wJTydzVgNMiYqvuShGxJ+W7csegNs5UZl4PnFUPlwO+ERGP6mrDchGxP2U14XtYsuedJGkZMq7JTiVJ0miavVaOy8zbpnNzZl4RET8GdmrE6x6adGdEPJvSA6PT+2Y7yvC6WyPiHOBqyiTTKwPrAI9lyYmyofTsOJ/7icz8dUS8AjiGqXmtzoqISylzH91AeT8eAjyeIT1nMvOOiNibMhzwAZRk5VkRcTYlybAisD3wiHrLm4FRVgn8GmWVvCfUGN+IiF9Q5uVavrbtSbXuQZRk18OHtPW0iHgT8N81xq7AcyPiQso8TzdS3pP16nPXGaGds+F1lNeybW3nB4F/iYgzKYm6oPy7bE1ZgRJGm+fpc5Q5t5o+P44GzxObAYcAh0TEFZR/007PsHUpn8O1GvW/kpk/7RHnVOA2SrL3icBvI+J0yt+KTlL+u5l57/DMzDw2InYC9q+nXge8LCJ+SFlo4SGU3l3NhNknM/O4Xi8kM2+LiH0pK42uAmwKnBMRPwcupHwntmVqyPEBwKc7t/eKuRTeR+kdtxzlO3dB/SxeRnk9T6N8ZwDeA7yBId9FSdL8ZHJMkqQJiYgtmUpqwPSHVDbv6yTHXhIR+3fPm1STbq+IiBOA9zM1YfyqwNOHxL+YMjTzvzJz1N5Oy4TMPDkinkpJjHR6o2xWt34WAlf2iXdORDyPknDr9EjaliUnCV8M/FtmHhoRQ5NjmXl3RLyIMuSsM5TryXW7txrw78DBlOTYUJl5WERcAnyWsgpfUJKijx1w22+YmgNt1mXmjRGxM/Apytxgy1MSj3/X55bbmeoRN8gJlGRRZ06sOyi9fe4PbqZ8HjpJwofRf+XIxZTv9lt6XczMv0XEPwOfqfE2Zeoz2Hzed7vuOyAirgHeSxleuTrwwh6PuB04ODMHrvyYmWfWIZNfpSRqg5Lg277rtRxMSXx2kmPNBS2WWmZ+v/YMO5Tyu2kFYOe6NdvxIcp8j28Y5/MlSZNjckySpMlp9hq7mq4eX9PwDcqPtZUoiYM9gSN7VczMYyLi65SE2LMoSbUNKL1uVqH8mLwB+C1lNczTMvOsXrHuLzLzl8DWEfF3wB6UIZPrAw+kJE2uowyX/Dll9c+fZWbfHimZ+aM6RHF/yrCxzSg/ov8I/Aj4bJ3zbDptvDwiHk8ZCvpiSi+ZlWrMHwP/3RkSOOL0YZ24P6xt3QPYjZJsWJey4uWtlJ4+FwE/pSwW8b/Tafc41MTuGyLiE5RFDJ5J6dW4FmUI6dWUnlHfA46pixgMi3lXRJzM1GT8x2fmxJJ+sykzvxER61ESiDtQev5tSvk8A/yNkvD+CfClzLxwSLz/iYgLgDdSelduQEmqD/ygZeaHIuIoSs+x51CG4z6Q0uvsMsp36fDMvGLE13VaXa3yAMrndVPK9+oqpr5X53QtrvHXUWJPR30/zgTeShnGvj6ld91VlL/hR2Tm+TC976IkaX6JAf+tJ0mSpDGKiHv/wysz/SU9IXUy+EuZmj/tWZn5/QG3aBlRh5B3erJ9OzN3HVRfkqRenJBfkiRJ93e7MJUYu4yZ99rU/POyRvmcOWuFJGmZZnJMkiRJ93dvbpQ/O2iYrJYddXXYVzdOfbVfXUmSBjE5JkmSpPutOrH77vXwJuDwOWyORhARD4uIr0fEjtFjIq+IWD4iXkWZx2yFevqbmXnRRBsqSbrfcM4xSZKkCXHOsdkXEY+gTOK+PGUhg2czNZn8+zPz3+aqbRpNRGwMXF4P/wScR1mI4R7gocBTKKtYdlwNbJWZV0+ulZKk+xOTY5IkSRNicmz2RcTOwA97XDoTeEZm3jnZFmm6upJjw5wL7JmZf5i1BkmS7vcWzHUDJEmSpFlyJyXJcgzwURNjy4bMXFjnE3sBsD2wIbA28EDgZuBa4GfAcZl50pw1VJJ0v2HPMUmSJEmSJLWWE/JLkiRJkiSptUyOSZIkSZIkqbVMjkmSJEmSJKm1TI5JkiRJkiSptUyOSZIkSZIkqbVMjkmSJEmSJKm1Fsx1A6RuEbESsGU9vA64Zw6bI0mSJEmS5oflgXVq+YLMvGMcQU2OaT7aEjhnrhshSZIkSZLmrW2Ac8cRyGGVkiRJkiRJai17jmk+uq5TOPvss1lvvfXmsi2SJEmSJGkeuPrqq9l22207h9cNqjsdJsc0H907x9h6663HhhtuOJdtkSRJkiRJ88/Y5id3WKUkSZIkSZJay+SYJEmSJEmSWsvkmCRJkiRJklrL5JgkSZIkSZJay+SYJEmSJEmSWsvkmCRJkiRJklrL5JgkSZIkSZJay+SYJEmSJEmSWsvkmCRJkiRJklrL5JgkSZIkSZJay+SYJEmSJEmSWsvkmCRJkiRJklrL5JgkSZIkSZJay+SYJEmSJEmSWsvkmCRJkiRJklrL5JgkSZIkSZJay+SYJEmSJEmSWsvkmCRJkiRJklrL5JgkSZIkSZJay+SYJEmSJEmSWsvkmCRJkiRJklrL5JgkSZIkSZJay+SYJEmSJEmSWsvkmCRJkiRJklrL5JgkSZIkSZJay+SYJEmSJEmSWsvkmCRJkiRJklrL5JgkSZIkSZJaa8FcN0Bqi43f9a37nFv40d3moCWSJEmSJKnDnmOSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJai2TY5IkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJaq3WJsci4iER8fyIODgiTo2I6yMi63bkDOLtGhHHR8SVEXFH3R8fEbtOI8aCiPiHiPhxRFwXEbdFxKUR8dmIeOw04qxdX9evIuLGuv2qnnvwNOI8rj770tqW62rb/iEiFowaR5IkSZIkab5qc4Lj2nEEiYjlgM8B+3Vd2qBue0TE4cAbM3PxgDhrA6cA23Rd2hR4A7BPRByQmYcPac92wAnAul2Xtqzb6yJij8w8e0ic1wOfBlZsnF4Z2LFur4mI3TLz+kFxJEmSJEmS5rPW9hzrcgXw3Rne+2GmEmPnA68Atq378+v51wEf6hcgIpYHjmcqMXYcsCuwHfBm4E/ASsBnB/VEi4iNgJMoibG7gY8DO9Xt4/XcesBJEbHhgDjPA/6Hkhi7trZhu9qm42q1bYHja9slSZIkSZKWSW3uOXYwcA5wTmZeGxEbA5dPJ0BEbA68vR6eC+yUmbfV43Mi4pvAGcDWwDsi4ojMvKRHqH0ovbEAPpOZ+zeunR0RpwLnAWsA/xkRW2Tm3T3ifBhYp5b/PjO/3rj244g4DzgGeAglWbdvj9e0AnAoJXF6I7BDZl7aqPLtiPgv4B9rm/cGjuzRFkmSJEmSpHmvtT3HMvMDmXlyZi7N8Mq3MJVgPLCRGOs841bgwHq4AHhrnzidBNsNwDt6tPUS4CP18BHAi7rrRMS6wCvr4Xe6EmOdOMcC36mHe9d7ur2IMpQT4CNdibGOdwB/aZQlSZIkSZKWSa1Nji2tiAhg93p4UWae1atePf+7erh7va8ZZ3Ngi3p4bE2o9XJko3yf5BjwQqb+Pb8woOmdOMvVe7rt0eeZ96ptPLYePqa+BkmSJEmSpGWOybGZ2wRYv5bPGFK3c30DYOOuazv2qHcfmXkNcHE93KFHlZHidF0bFOd39ZkzjSNJkiRJkjTvmRybucc0yhcNqdu8vkXXtZnE2SgiHtAnzt8GJbUy82rKXGL3aUtErAZsNM223CeOJEmSJEnSsqLNE/IvreZqj1cOqbuoUd6o69pM4kS973eNa504w2J04jx2TG2hRwbYrugAACAASURBVJyBBq2UWfWaC02SJEmSJGnsTI7N3OqN8s1D6t7SKK82y3GGxWjGma22DLNoeBVJkiRJkqTZ57DKmVu5Ub5zSN07GuVVZjnOsBjNOLPVFkmSJEmSpGWCPcdm7vZGecUhdVdqlG8bEud2+hsWZ9UR2tKMM6wto8ToFWeYYcMw1wXOmWZMSZIkSZKkaTM5NnM3NcrDhhU2J8/vHq7YHWdQcmxYnFVHaEszzrC2jBKjV5yBMnPgfGYRMZ1wkiRJkiRJM+awyplrJniGTTDf7CnVPd/WTOIk950wv3M8LEYzTndbrppBW3rFkSRJkiRJWiaYHJu5CxvlRw+p27z+2zHEWZSZt3Rd68RZMyL6rvYYEesBa/RqS2bexFSia2lekyRJkiRJ0jLB5NjMXQ78sZafPqTuTnV/FbCw69pPGuW+cWrCa/N6eGaPKiPF6bo2KM6jBiXZRogjSZIkSZI075kcm6HMTODEevjoiNi+V716vtPL6sR6XzPOxUz1vHppRKza55H7NsrH97j+TWBxLb9mQNM7cRbXe7qd0OeZ96ptfGk9vLC+BkmSJEmSpGWOybGl80ngnlo+NCJWaV6sx4fWw7tr/V7+o+7XAj7efTEiNgPeXQ8voUdyLDOvAb5SD58TEXv2iLMX8Jx6eFS9p9vxwGW1/O767G6HAA9qlCVJkiRJkpZJrV2tMiJ2BB7ROLV2o/yIiNi3WT8zj+yOkZkXR8QhwLuArYEzI+JjwKXAZsA7gSfV6odk5u/7NOeLwGuBHYD963DGw4C/ANsC76PME7YYeHNm3t0nznuA5wLrAEdHxNbAyfXa84G31fJ1wHt7BcjMuyLiQOCk+swzI+JDwNmUhNjrgZfU6j8BjurTFkmSJEmSpHkvukb5tUZEHAnsM2r9zIw+cZajJLJeO+D2zwNvyMzF/SpExNrAKcA2farcARyQmYcPamdEbEcZGtlvvrBrgD0y8+dD4rwe+DSwYp8qZwO7Zeb1g+LMRERsSF0YYNGiRWy44SgLcM5/G7/rW/c5t/Cju81BSyRJkiRJWvZceeWVbLTRRp3DjTLzynHEdVjlUsrMxZm5H7AbZQ6yPwJ31v2JwPMy83WDEmM1zvXAU4F/pPTI+jNwO2WI42HAVsMSYzXOz4EtgQ8BvwZurtsF9dzjhiXGapzDgK3qsy+rbflzbdubgB1mIzEmSZIkSZI0Sa3tOab5y55jkiRJkiSpmz3HJEmSJEmSpDEzOSZJkiRJkqTWMjkmSZIkSZKk1jI5JkmSJEmSpNYyOSZJkiRJkqTWMjkmSZIkSZKk1jI5JkmSJEmSpNYyOSZJkiRJkqTWMjkmSZIkSZKk1jI5JkmSJEmSpNYyOSZJkiRJkqTWMjkmSZIkSZKk1jI5JkmSJEmSpNYyOSZJkiRJkqTWMjkmSZIkSZKk1jI5JkmSJEmSpNYyOSZJkiRJkqTWMjkmSZIkSZKk1jI5JkmSJEmSpNYyOSZJkiRJkqTWMjkmSZIkSZKk1jI5JkmSJEmSpNYyOSZJkiRJkqTWMjkmSZIkSZKk1jI5JkmSJEmSpNYyOSZJkiRJkqTWmlhyLCJWjYhVB1w/MCJ+HBG/jYhTIuIFk2qbJEmSJEmS2mkiybGa6LoJuDoiVu9x/Qjgk8BTgUcBzwFOiIh3T6J9kiRJkiRJaqdJ9Rx7DhDANzPzpuaFiNgR2Lce3gqcD9xe6x8cEY+bUBslSZIkSZLUMpNKjm0PJPDDHtfeUPd/BLbIzK2ARwOLKO1740RaKEmSJEmSpNaZVHLsIXX/ux7XnktJnB2amVcCZOYi4FBK77GnT6SFkiRJkiRJap1JJcfWqfvuIZWPBdauhyd23XNu3T98FtslSZIkSZKkFptUcuyeul+r6/yOdX9dZnb3KvtL3a88a62SJEmSJElSq00qOXZV3T+x6/xulCGVP+5xz5p1f/1sNUqSJEmSJEntNqnk2I8p84cdEBFrA0TENpT5xgC+0+OeLer+mtlvniRJkiRJktpoUsmxzwCLgU2AyyLiXOAMYAFl+OQxPe55BqVX2YUTaqMkSZIkSZJaZiLJscz8BfAOSrJrNeDJlLnE7gJen5ndE/WvSRlyCXD6JNooSZIkSZKk9lkwqQdl5v+NiNOAPYF1gauBo3tMxA+wM3BOLZ88mRZKkiRJkiSpbSaWHAPIzAuAC0aodyJw4uy3SJIkSZIkSW02keRYRBxRi6dm5tcn8UxJkiRJkiRpmEn1HNun7ntNvC9JkiRJkiTNiUmtVnld3V87oedJkiRJkiRJQ00qOXZh3T98Qs+TJEmSJEmShppUcuzLQDA1vFKSJEmSJEmac5NKjn0B+D6we0QcFBExoedKkiRJkiRJfU1qQv6nAf8BrAO8D3hZRBwD/Ar4C3DPoJsz80ez3kJJkiRJkiS1zqSSY6cD2TjenJIkG0UyuXZKkiRJkiSpRSaZdHIopSRJkiRJkuaVSSXHdpnQcyRJkiRJkqSRTSQ5lplnTOI5kiRJkiRJ0nRMarVKSZIkSZIkad4xOSZJkiRJkqTWmvgqkBGxJrAn8BRgXWBV4DWZ+YdGnfWBBwK3Z+Zlk26jJEmSJEmS2mGiybGIOAD4MLBa5xSQwAO6qu4MfBm4PSI2zMwbJtZISZIkSZIktcbEhlVGxAeBTwGrA3cC5w2o/jXgGmAl4CWz3zpJkiRJkiS10USSYxGxFfDeevhlYN3M3LZf/cxcDHyd0rPs2bPfQkmSJEmSJLXRpHqOHUBJdP0sM1+dmX8b4Z6f1f2Ws9csSZIkSZIktdmkkmM7UeYW+/Q07llY9xuMvTWSJEmSJEkSk0uOrVf3v5vGPbfX/UpjboskSZIkSZIETC45dmfdP3Aa9zy07v865rZIkiRJkiRJwOSSY1fU/SOncc8z6n46vc0kSZIkSZKkkU0qOfZ9yoT8/zBK5YjYAHgDZZ6y785iuyRJkiRJktRik0qOfRq4C3hCRLxvUMWIeBTwbWBN4Fbgs7PfPEmSJEmSJLXRgkk8JDMvjYj3AB8HDoqI3YDjGlX2ioi7gB2Av6Mk7RJ4S2ZeN4k2SpIkSZIkqX0mkhwDyMz/iIgAPgRsC2xDSYABvL9RNYB7gLdn5ucn1T5JkiRJkiS1z6SGVQKQmYcATwS+AFxPSYQ1txuBo4EnZeanJtk2SZIkSZIktc/Eeo51ZOZvgf0AIuJhwEOA5YE/A5dl5uJJt0mSJEmSJEntNPHkWFNmXgFcMZdtkCRJkiRJUntNdFilJEmSJEmSNJ+YHJMkSZIkSVJrjXVYZUQcUYuZmfv1OD8TS8SSJEmSJEmSxmXcc47tC2Qt79fn/HREvc/kmCRJkiRJksZu3MmxK+idBOt3XpIkSZIkSZozY02OZebG0zkvSZIkSZIkzaWxTsgfEWtExBrjjClJkiRJkiTNlnGvVvlX4IaIeEzzZES8um4mziRJkiRJkjRvjHvOMSiT6Hc7kjLn2LnAhbPwTEmSJEmSJGnaxt1z7J66X3HMcSVJkiRJkqSxG3dy7Pq6f8zAWpIkSZIkSdI8MO5hlT8D9gA+FhFrAhcDdzWubxMRa083aGb+aEztkyRJkiRJku417uTY/wFeAKwPfLrrWgBHzCBmMjtzo0mSJEmSJKnlxjqsMjPPBF4MXEpJhnW2jpjhJkmSJEmSJI3d2HtkZeZJwEkRsRGwAbAy8ANKD7D9gMvH/UxJkiRJkiRpJmZtuGJmLgIWAUTc2/nr7My8cLaeKUmSJEmSJE3HpOby+hKl59hfJvQ8SZIkSZIkaaiJJMcyc99JPEeSJEmSJEmajrFOyC9JkiRJkiQtS8bacywiHtYpZ+YVvc7PRDOWJEmSJEmSNC7jHlbZWYkyu2IvzQqV3bEkSZIkSZKksRh30immeV6SJEmSJEmaM+NOjr1mmuclSZIkSZKkOTPW5FhmfnE65+9PImJF4NXAXsDjgbWAu4CrgJ8Ch2XmT0eIsyvwBmAbYB3gOuAc4HOZeeqIbVkAvA54JfBoYDXgj8BpwH9m5m9GjLM28GZgD2DjenohcALwqcz88yhxJEmSJEmS5ivn8hqDiHg48C3gsV2XVgQ2r9u+EXEo8E+ZmT1iLAd8Dtiv69IGddsjIg4H3piZiwe0ZW3gFEpyrWlTStJtn4g4IDMPH/KatqMkwdbturRl3V4XEXtk5tmD4kiSJEmSJM1ny03iIRHx6rqtMY17VuvcN5ttW1oRsQJLJsZ+BewLPAX4O+Bg4JZ67UDgnX1CfZipxNj5wCuAbev+/Hr+dcCHBrRleeB4phJjxwG7AttReoD9CVgJ+GztodYvzkbASZTE2N3Ax4Gd6vbxem494KSI2LBfHEmSJEmSpPkuenRiGv9DIhZTVp3cMjMvHPGezYDfA4szc972cIuIPYGv18OfAU/LzHu66mxVr60A/BVYJzPvblzfHPgNpSffucBOmXlb4/qqwBnA1pTE1BaZeUmPtrwW+Hw9/Exm7t91/RHAecAawCU1zt10iYgvAXvXw5dm5te7rr8UOKYefjEz973vOzNzNeG2CGDRokVsuOH9I/+28bu+dZ9zCz+62xy0RJIkSZKkZc+VV17JRhtt1DncKDOvHEfcifQcW0rzfaXLpzbKH+lOjAFk5nnAyfXwgcAWXVXewtQQ1wObibF6/62UXmfUem/t05a31/0NwDt6tOMS4CP18BHAi7rrRMS6lLnKAL7TnRircY4FvlMP9673SJIkSZIkLXPmc3Js+bq/T8+meWbFRvmyAfUu7XVPRASwez28KDPP6nVzPf+7erh7ve9etfdZJ+l2bE2o9XJko3yf5BjwQqY+F1/oE6MZZ7l6jyRJkiRJ0jJnPifHHlX3N8xpK4b7XaO86YB6m9V9UoaLdmwCrF/LZwx5Vuf6BkytHtmxY49695GZ1wAX18MdelQZKU7XtV5xJEmSJEmS5r1ZmcsrInbqc2mbupriICtREklvpySS/necbZsFR1MmyV8DeGdEnNJjzrEnAZ3Jpb6amTc2Lj+mUb5oyLOa17cALl+KOJsDG0XEAzLzlsa1Tpy/1URaT5l5dUTcSHnd3cNEJUmSJEmSlgmzNdH96ZTEVlMAR0wjRtQYnx1Tm2ZFZl4fEXtTkmQ7AOdExCcpvbNWq+feRhlK+YtabmrONj9sIrlFjfJGXddmEifqfc3eb504o0xqt4iySmd3WwYaYYVL5zCTJEmSJEkTMZurQPaaSH86k+tfCfx7Zp4wpvbMmsz8Zl2R8m3AfsAXu6pcC7wPOKzHXGCrN8o3D3lUs4fXarMcZ1iMZpzuGMMsGl5FkiRJkiRp9s1WcmyXRjmAH1B6ge3HkkMBuyVwO3B1Zi4zCZSIWBF4NWVi/V4JwIcCr6K89m92XVu5Ub5zyKPuaJRXmeU4w2I043THkCRJkiRJWibMSnIsM5eYyL2xsOLZmXnhbDxzrkTEA4BTgacB9wAfp6zyeBkl0bQd8H7KRPcnRMTbM/MTjRC3N8rNlS97WalRvq3rWnec2+lvWJxVR2hLM053jGGGDcNcFzhnmjElSZIkSZKmbTaHVTZtUvdXTeh5k3QQJTEGsF9mNodU3gl8LyJ+CHyX0qPukIj4fmb+sta5qVF/2PDEBzTK3cMeu+MMSo4Ni7PqCG1pxhllCOa9MnPgfGaNZKokSZIkSdKsWm4SD8nMP9Tt7kk8b1KiZHFeWw8v7kqM3au+7vfVw+WAfRuXm4miYRPVN3tcdQ87nUmc5L4T73eOh8VoxllmhsBKkiRJkiQ1TSQ5dj/2UGCtWj5/SN3zGuVHN8oX9jnfS/P6b7uuzSTOosy8petaJ86aEdF31ciIWA9Yo09bJEmSJEmSlgmTGlYJQEQsAHajDEPclLIy4vJDbsvMfOZst22Gmj3hhr2XK/S573Lgj8D6wNOHxNip7q8CFnZd+0mj/HTga70C1ITX5vXwzB5VfgLs3YhzTJ+2NNvaK44kSZIkSdK8N7HkWETsCBwFPKx5esAtWa/nbLZrKd0A3EjpQfWUiFgwYOhoM5l074qdmZkRcSLwJuDREbF9Zp7VfXNEbM9Uj68TM3OJ9yUzL46I3wJbAC+NiLdl5q092rFvo3x8j+vfBP6b0qvwNfRPjnXiLOa+K3BKkiRJkiQtEyYyrDIiHg18m5IYC+AuyvC9HwNn9Nl+1NjPS5m5GPhWPVwfeE+vehHxIOBjjVMnd1X5JGWlS4BDI2KVrvtXAQ6th3fX+r38R92vRVk1s7sdmwHvroeX0CM5lpnXAF+ph8+JiD17xNkLeE49PKreI0mSJEmStMyZVM+xf6WsgHgP8AHgPzNzWisczmMHA7tTXt9BEbEV8EXgMmBlYHvgLUz1mPt+Zn63GaD2+joEeBewNXBmRHwMuBTYDHgn8KRa/ZDM/H2ftnyRskDADsD+dQjlYcBfgG0piwKsQent9eYBvdzeAzwXWAc4OiK2Ziqh93zgbbV8HfDe/m+NJEmSJEnS/Dap5NgzKMMjP5WZ/z6hZ05EZl4UEbsDRwNrAy+oWy8/APbqc+09wEMoya0n0XvOsM8zIBmVmfdExB7AKcA2wEvq1nQHcEBmnjogzqKIeAFwArAuJTn3zq5q1wB7ZGb3apeSJEmSJEnLjEmtVrl23fea42qZl5mnUeYDeydwOqVH1V3AbZT5xY4F9gCelZl/6RNjcWbuR1mw4ETKJP131v2JwPMy83V1KOegtlwPPBX4R8rk+n8Gbqf0ZDsM2CozDx/hNf0c2BL4EPBr4Oa6XVDPPa7WkSRJkiRJWmZNqufYdZQ5uW6b0PMmLjP/TJnn6z5zfU0zzimUnl9LE+NuyqT6/72Uca6nDMV839LEkSRJkiRJmq8m1XPsJ3X/uAk9T5IkSZIkSRpqUsmxT1Am4/+niJhUbzVJkiRJkiRpoIkkxzLzHMqKjU8AjouItYfcIkmSJEmSJM26ifTiioj31+LZwPOBP0TE94CLgFuH3Z+ZB89i8yRJkiRJktRSkxrieBCQtZzAKsAL6jYKk2OSJEmSJEkau0nO/xVDjiVJkiRJkqSJmkhyLDMnNfG/JEmSJEmSNDKTVpIkSZIkSWotk2OSJEmSJElqLZNjkiRJkiRJaq2JJ8ci4pkRcVREXBIRN0fE3RHxmK46O0XEP0bEqybdPkmSJEmSJLXHxFarjIhVgS8CL+6cqvvsUf0e4NNARsTPM/P3E2iiJEmSJEmSWmaSPceOpSTGAjgH+I9+FTPzTODX9fAls980SZIkSZIktdFEkmMR8RLgefXwDZm5fWb+y5DbjqMk0p4+q42TJEmSJElSa02q59g+df/lzDx8xHvOq/stZqE9kiRJkiRJ0sSSY1tT5hY7Zhr3XF3364y/OZIkSZIkSdLkkmMPrvs/TuOexXU/8RU1JUmSJEmS1A6TSjz9re7Xn8Y9m9T99WNuiyRJkiRJkgRMLjl2cd0/YRr37FH354+5LZIkSZIkSRIwueTYtygrTx4YESsPqxwRTwNeTpmn7KRZbpskSZIkSZJaalLJsf8CbgAeCnwjItbqVSkiFkTE64GTa9sWAUdOqI2SJEmSJElqmQWTeEhm3hgRLwNOAXYFFkXEGY0qH4+IFSmrWq5J6WV2O/DSzLxrEm2UJEmSJElS+0xsJcjM/D7wDOAKYBXguZRhk1ASZs8EHkhJjC0CdsnMsyfVPkmSJEmSJLXPRHqOdWTmmRHxSMp8Yi+k9BR7CLA88GfK5PvfBL6YmXdOsm2SJEmSJElqn4kmxwAy827gy3WTJEmSJEmS5szEhlVKkiRJkiRJ843JMUmSJEmSJLWWyTFJkiRJkiS11ljnHIuIe8YZr8rMnPjcaJIkSZIkSbr/G3fSKcYcT5IkSZIkSZo1406OfXDI9d2ArWv5N8DZwLX1+KHANsDjgATOBU4Zc/skSZIkSZKke401OZaZfZNjEfF+SmLsl8AbMvOcPvW2AT5b634rMw8eZxslSZIkSZKkjolMyB8RzwQOAi4GduyXGAOo154GXAJ8ICKeNYk2SpIkSZIkqX0mtVrlmylDJT+ambcMq1zrfJQyh9mBs9w2SZIkSZIktdSkkmOdecZ+NY17fln324y5LZIkSZIkSRIwueTYWnW/5jTuWaPuHzTmtkiSJEmSJEnA5JJjf6z7l0zjnj3r/uoxt0WSJEmSJEkCJpcc+zZl/rA3RsRLh1WOiD2BN1LmKTtlltsmSZIkSZKklppUcuzfgRvr846OiBMiYo+I2CAiVoiIBbW8R0QcDxwDLA/cBHxkQm2UJEmSJElSyyyYxEMy86qIeAFwEmUusRfUrZ+gJMZ2z8yrJtBESZIkSZIktdCkeo6RmT8GtgT+H7CYkgDrtS0GjgMen5lnTKp9kiRJkiRJap+J9BzryMxFwF4R8VBgF0qyrLOS5V+AC4AfZuY1k2yXJEmSJEmS2mmiybGOzLwW+FrdJEmSJEmSpDkxsWGVkiRJkiRJ0nxjckySJEmSJEmtNdZhlRGxU6ecmT/qdX4mmrEkSZIkSZKkcRn3nGOnA1m3BT3Oz0R3LEmSJEmSJGksZiPpFNM8L0mSJEmSJM2JcSfHdpnmeUmSJEmSJGnOjDU5lplnTOf8/2fvzsN2Lct68X9PYDuA4ISKwEocIkipTNBU1NS2pljhTi1zpxBklkNampjD0aCJQ+XU4JRD7dzSVhxCf5oNOGxHfuaQA6GiC5UETQUBEda5/3jut/X48o5rPe/9vms9n89xPMc9Xfd5n4uXv77HdV83AAAAAGwmX6sEAAAAYG4JxwAAAACYW8IxAAAAAOaWcAwAAACAuSUcAwAAAGBuCccAAAAAmFvCMQAAAADmlnAMAAAAgLklHAMAAABgbgnHAAAAAJhbwjEAAAAA5tZ+Yz+wqq6f5EFJ7pzkkCT7Jzm5u784NebQJDdIckV3f37sHgEAAACYD6OGY1X1mCTPSnK9hVNJOskBi4b+ZJK/SXJFVR3e3d8YrUkAAAAA5sZor1VW1e8neWGSA5NcmeScFYb/7yQXJrl2kp/f+O4AAAAAmEejhGNVdYckTxsO/ybJId19x+XGd/eOJH+Xycyy/77xHQIAAAAwj8aaOfaYTIKu93f3w7v7W2u45/3D9piNawsAAACAeTZWOHb3TNYWe8k67jl/2B42824AAAAAIOOFYzcftp9dxz1XDNtrz7gXAAAAAEgyXjh25bC9wTruudmw/eaMewEAAACAJOOFY18atj+4jnvuNWzXM9sMAAAAANZsrHDsHzNZkP9RaxlcVYcleWQm65S9cwP7AgAAAGCOjRWOvSTJ95L8aFU9faWBVfVDSf6/JNdPclmSl258ewAAAADMo/3GeEh3f66qnprkuUl+r6pOSPLGqSEPrqrvJblrkvtkEtp1ksd390Vj9AgAAADA/BklHEuS7n5+VVWSZya5Y5LjMgnAkuQZU0MrydVJntjdrxyrPwAAAADmz1ivVSZJuvt5SX4syauSXJxJEDb9+3aS1yW5fXe/cMzeAAAAAJg/o80cW9Ddn05ySpJU1Q8kuWmSfZN8Pcnnu3vH2D0BAAAAMJ9GD8emdfeXknxpM3sAAAAAYH6N+lolAAAAAGwlwjEAAAAA5tYor1VW1T/txu3d3feeWTMAAAAAMBhrzbGfTNKZfJFyOb3ouJY5DwAAAAAzMVY49u6sHnIdkOQ2SW4wjD03yVc3uC8AAAAA5tgo4Vh3/+Rax1bV/ZO8KMmNkpzS3e/bqL4AAAAAmG9bbkH+7n5bkuOTXJXkzKo6bJNbAgAAAGAvteXCsSTp7guT/GmSg5P8zia3AwAAAMBeakuGY4P3DtsTNrULAAAAAPZaWzkcu3LYHrqpXQAAAACw19rK4djxw/ayTe0CAAAAgL3WlgzHqurOSZ6RpJN8aJPbAQAAAGAvtd8YD6mqZ6xh2D5Jbpjk2CR3Go47k4X5AQAAAGDmRgnHkvxeJkHXWlWSq5L8Tnf/w4Z0tEGq6geSnJLJhwRukeTAJBclOT/JPyc5o7s/ucL990vyyCTHJbnJcO+Hk7ysu9++xh72S3JqkoclOSrJ9ZJ8Jcm7kryou/9tjXUOTvK4JCcmOWI4fX6SNyV5YXd/fS11AAAAALaqscKxZBJ4raSTXJLkC0nOziQM+tSGdzVDVfXYJM9OcsCiS4cPv+OTHJTk8Uvcu0+Sl2USrE07bPidWFWvSPJr3b1jhR4OTvK2TMK1abfKJHR7RFU9prtfscq/5U6ZhGCHLLp0zPA7tapO7G6vvQIAAAB7rFHCse7ekmubzVJVPS3JHw6H5yZ5eSYzvr6V5MZJbp/kgUmWC7aelZ3B2EeTPDfJ55LcOsnvDPefmslMst9dpod9k5yZncHYG4c+vpHJq6pPS3LTJC+tqi8vNxOtqrYleWsmM9euSvInSf5+uPyAJL+V5OZJ3lpVd+juC5b5NwEAAABsaWPOHNtrVdW9szMYe22SU7v7e4uG/WOS51fVtZa4/8gkTxwOP5Lk7t19+XD84ap6Syaz6Y5N8qSq+qvuPm+JVh6RnV/5/PPufvTUtQ9V1duTnJPJ7LUXVdXR3X3VEnWelUkwliS/1N1/N3XtPVV1TpLXZxK0PTPJSUvUAAAAANjy9voZXRtteB3yL4bDjyU5ZYlg7L9095VLnH58dgaVj50KxhbuuSzJY4fD/ZI8YZnyCwHbN5I8aYlnn5fJa59JcptMZrJ9n6o6JJO1ypLkHYuCsYU6ZyR5x3D4y8M9AAAAAHsc4djuu0+SHxz2n7PMTKxlVVUl+bnh8DPd/YGlxg3nPzsc/txw33SdI5McPRyeMQRqS3n11P41wrEkP5ud/1+8aoXWF+rsM9wDAAAAsMcZ5bXK4QuOM9fdX9qIuuv04GHb2bkuV6rqRpmsNfb17v7GCvffMsmhw/7Zqzzr7CQ/lMkC/Udk8vGCBccvGrek7r6wqs5NcmSSuy4xZE11Fl27ayYfEwAAAADYo4y1EdLHowAAIABJREFU5tgXVh+ybp2tsWbaTwzb87v7kqr6pSRPSXK7hQFDGPXyJC/u7u8uuv+Hp/Y/s8qzpq8fne//77reOkcm2VZVB3T3d5ao863uvnC5At391ar6dibrlx293DgAAACArWyscKlWH7LnGdYbO2o4vLiqXpjkcUsMPTLJ85I8sKpO6O5vTl07fGp/ta8+bp/a37bo2q7UqeG+z05dW6izli9Qbk9y2yV6WVFVHb7KEGuYAQAAAKMYKxw7edj+RpLjknwvyTuTfCjJfwzXbjZcu0+S/5bJVxv/fKT+dtX1s3N9rmMy6f+rmSyG/7YkVwznnpPJDLO7JPmrJP9jqsaBU/uXrvK86Rle11t0bdZ1VqsxXWdxjdVsX30IAAAAwMYbJRzr7tdU1SuTHJtJKHZKd395qbFVdVgmryDeN8nduvvUMXrcRQdM7V8nyWVJ7tnd0zOx3l1V90ry/iQ/msnssTt19wen7luw1Jcsp02/knndRddmXWe1GtN1FtcAAAAA2COM8rXKqnpQJrPHPpLkhOWCsSQZrv1MknOSnFxVDxmjx110xaLjVywKxpIk3X15kqdOnfqFZWpca5XnXXtq//IVeplFndVqTNdZXGM121b5HbfOegAAAAC7ZKzXKn8tkwX0/6S7r15tcHdfXVV/nOR1SR6Z5IwN7m9XXbLo+J0rjP3HJFdl8t98OvyZrrHa64nTM9UWv/a4uM7i4G49dfZfQy/TddbyCuZ/6e4V1zOr2iuXqAMAAAC2oFFmjiX5kWF77jruWRh7zIx7mZnhy5MXTZ1adi2t7r4iycXD4U2mLk0HRastVD+98P3iZ+1Knc41F95fOF6txnQda4gBAAAAe6SxwrGFRd5vuo57FsYeuOKozfdvU/v7rjJ24fpVU+c+NbV/VFY2ff3Ti67tSp3t3f2dRdcW6ly/qpb9amRV3TzJQcv0AgAAALBHGCsc++Kwffg67lkY+6UZ9zJr757av9Vyg6rqoCQHD4fTa659IclXhv17rPKsu0/df/6ia++d2l+2zhB4HTkcvm+JIWuqs+jaUnUAAAAAtryxwrE3J6kkv1hVv7Pa4Kp6YpKHZvLa35kb3NvuesPU/gNXGPfATP4bJMl7Fk52d2fy3ydJjqqqn1jq5uH8woyvNw/3/ZfuPjc7Z3A9pKr2X6aPk6b2l/pv+5YkO4b9k5epMV1nx3APAAAAwB5nrHDs9CRfHfafXVUfrarHV9Vdq+oHq+o2w/7jq+qcJM8Zxl44tb8ldffHk7x9OHxoVd178ZhhttYzh8Mrk7xq0ZAXJFn4UMGLq+q6i+6/bpIXD4dXDeOX8vxhe6Mkz12ij1snecpweF6WCMe6+8Ik/2s4vO/wpdHFdR6c5L7D4V8P9wAAAADscUb5WmV3f7OqfirJOzJZ6P1HkvzxCrdUJgvD/3R3f3OEFnfX45PcOckNkvx9Vb0gyduSXJ7kjpkEUgsL3D+9u6dfq0x3n1tVz0tyWpJjk7yvqp6T5HNJbp3kyUluPwx/Xnf/+zJ9vCbJryS5a5JHD6Hcy5P859DH0zNZJ2xHksd191XL1Hlqkp/O5MMBr6uqY5P8/XDtAUl+e9i/KMnTVvjvAgAAALCl1aK38zb2YVUHJnlGJgHODZcZ9p+ZzKz6g+7+9li97a6qOj7J/0lys2WGdJJndffTl7l/n0yCrF9Z4TGvTPLI7t6x3ICqOjiTYO64ZYZ8N8ljuvsVKzwnVXWnJG9Kstyi/BcmObG7P7hSnV1RVYdn+ALm9u3bc/jha/lw5tZ3xGlnXePc+aefsAmdAAAAwJ7nggsuyLZt2xYOt3X3BbOoO8rMsQXdfUmSJ1XV7ya5Q5JjMnkFMJmEYp9Ick53XzlmX7PQ3e+tqtsmeWySE5PcMsm1Mnmd9F+SvLi7P7rC/TuSnFJVb0jyyEzCrYOTXJzkw0le2t1vX+7+qToXV9Vdkvxqkl9KcnSSAzJZ9P8fk7ywu/9thRILdT5YVcck+c3h33PEcOkLmayR9oLu/vpqdQAAAAC2slFnjsFamDkGAAAALLZRM8fGWpAfAAAAALYc4RgAAAAAc2uma45V1cMX9rv7tUud3xXTtQAAAABgVma9IP+rM/kqYyd57RLnd8XiWgAAAAAwExvxtcpa53kAAAAA2BSzDsduuc7zAAAAALBpZhqOdfcX13MeAAAAADaTr1UCAAAAMLeEYwAAAADMLeEYAAAAAHNrI75WuayqunGS/5nkbkluleTAJPuuclt39603ujcAAAAA5s9o4VhVPTjJy5IctHBqjbf2xnQEAAAAwLwbJRyrqjsl+dtMXuOsJF9J8tEk30iyY4weAAAAAGCxsWaOPTmT1ycvT/Kr3f23Iz0XAAAAAJY11oL8d8nk9cjTBWMAAAAAbBVjhWM3GLbvGOl5AAAAALCqscKxrw5bi+sDAAAAsGWMFY69a9jeYaTnAQAAAMCqxgrHnp/kiiRPrKrrjfRMAAAAAFjRKOFYd382ycOSHJrkH6vqtmM8FwAAAABWst8YD6mqvxp2P5XkuCQfr6pPJPlMkstWub27+5SN7A8AAACA+TRKOJbkpOxcjL+TVJJjht9KahgvHAMAAABg5sYKx74UX6oEAAAAYIsZJRzr7iPGeA4AAAAArMdYX6sEAAAAgC1HOAYAAADA3BKOAQAAADC3RllzrKp+YHfu7+4vzaoXAAAAAFgw1tcqv7Ab93bG6xMAAACAOTJW6FQjPQcAAAAA1myscOzkNYw5IMmRSX4+yWFJ3pfkFRvZFAAAAADzbZRwrLtfs9axVfWkJH+a5NeTvK+7T9uwxgAAAACYa1vua5Xd/b3ufkySf0nypKq67ya3BAAAAMBeasuFY1NemslaZY/d7EYAAAAA2Dtt5XDs34ftsZvaBQAAAAB7ra0cjl1/0RYAAAAAZmorh2OPGLZf3dQuAAAAANhrbblwrKp+sKr+MpNwrJO8bZNbAgAAAGAvtd8YD6mqz69h2D5JbpDkwKlzX0vyrA1pCgAAAIC5N0o4luSIXbjn/Ul+pbu9VgkAAADAhhgrHHvNGsbsSHJJki8kObu7/3VjWwIAAABg3o0SjnX3yWM8BwAAAADWY8styA8AAAAAYxGOAQAAADC3hGMAAAAAzC3hGAAAAABzSzgGAAAAwNwSjgEAAAAwt4RjAAAAAMwt4RgAAAAAc0s4BgAAAMDcmmk4VlVvrKo3VNXhs6wLAAAAABth1jPHThx+B02frKodVXVVVf3wjJ8HAAAAALtso16rrDWeAwAAAIBNM+tw7JJhe7MZ1wUAAACAmZt1OPaZYfubVXW9Ja73jJ8HAAAAALtsvxnX+9skxyV5QJJvVNV/JPne1PV3VtX3lrxzed3dt55VgwAAAACwYNbh2IuT3DXJg4bah01dq0XHa2W2GQAAAAAbYqbhWHfvSPKQqrpzkp/KJAy7dpJHZBJyvSXJN2f5TAAAAADYVbOeOZYk6e73J3n/wnFVPWLYfWp3f2ojngkAAAAA6zXrBfkBAAAAYI+xITPHFutuIRwAAAAAW47QCgAAAIC5NcrMsWlVtW+SEzNZsP92SW40XPpGkk8meVeSN3X31WP3BgAAAMB8GTUcq6qfTvKyTL5i+V+nh20nuUuSRya5oKoe2d3vGLM/AAAAAObLaK9VVtUvJ/n7TIKxGn5fTPKB4ffFhaFJtiU5q6oeNlZ/AAAAAMyfUcKxqrpFJjPG9klyWZKnJTmku2/V3XcZfrdKckiSpya5dBj78qr6gTF6BAAAAGD+jDVz7DeTXDuT0Otu3f1H3f21xYO6+6LufnaSuw1jrz3cCwAAAAAzN1Y4dp9M1hR7Xnf/62qDu/tjSZ6fySuW993g3gAAAACYU2OFYwuvRr5rHff8w6J7AQAAAGCmxgrH9h22V6/jnquG7WgfDQAAAABgvowVPH152N5lHfcsjP3KjHsBAAAAgCTjhWP/nMn6YadV1aGrDR7GnJbJOmX/tMG9AQAAADCnxgrHXpxkR5KbJPlgVT2oqvZdPKiq9qmqByV5f5KbDfe8ZKQeAQAAAJgz+43xkO7+ZFU9Pcmzkhya5PVJvllV/3+Sr2UyQ+xmSX48yQ0ymWWWJE/v7k+O0SMAAAAA82eUcCxJuvvZVfWtJM9Nsn+SGya516JhC6HYZUme1N1/MVZ/AAAAAMyf0cKxJOnuP6+qM5KcnOSnktwuyY2Gy99I8skk70ryqu6+eMzeAAAAAJg/o4ZjSTKEXs8bfgAAAACwacZakB8AAAAAthzhGAAAAABzSzgGAAAAwNwSjgEAAAAwt4RjAAAAAMwt4RgAAAAAc0s4BgAAAMDcEo4BAAAAMLeEYwAAAADMrf3GeEhVPWPY/WB3v2OMZwIAAADAakYJx5L8XpJO8sCRngcAAAAAqxrrtcqvD9svjfQ8AAAAAFjVWOHYecP2kJGeBwAAAACrGisce32SSvKQkZ636arqOVXVU7+fXMM996uqM6vqgqr67rA9s6rut47n7ldVj6qq91TVRVV1eVV9rqpeWlW3XUedg6vqD6rq41X17eH38eHcjddaBwAAAGArGysc+/MkH0vy8Ko6aaRnbpqq+rEkv7WO8ftU1SuSvC3JiUkOS3KtYXtikrdV1curasW/V1UdnOT/JvmLJMcnOTjJdZLcKskjk5xTVaeuoZ87JflEkqcnOSbJgcPvmOHcJ6rqjmv99wEAAABsVWOFY4ckOTXJJ5O8sqreWVUnVdWPV9Utq+oHVvqN1ONMDAHWyzL52MHX1njbs5KcMux/NMlDk9xx2H50OH9qkmeu8Nx9k5yZ5Ljh1BuT3C/JnZI8bujl2kleutJMtKraluStmfzNrkry3CR3H37PHc7dPMlbq+rwNf77AAAAALaksb5WeX4mX6tMJq9X3nv4rUVnvD5n4XGZBFSfySSsespKg6vqyCRPHA4/kuTu3X35cPzhqnpLkrOTHJvkSVX1V9193hKlHpHJbLEk+fPufvTUtQ9V1duTnJPkoCQvqqqju/uqJeo8K8lNhv1f6u6/m7r2nqo6J5PXZG+aSVh30kr/PgAAAICtbKyZY8kkFKtF+2v97RGGWW5/OBw+KsmVa7jt8dkZ/j12KhhLknT3ZUkeOxzul+QJy9RZCNi+keRJiy8Ogdqzh8PbJHngEv0fkuRhw+E7FgVjC3XOSPKO4fCXh3sAAAAA9khjzcg6eaTnbLY/S3K9JK/p7rOr6p4rDa6qSvJzw+FnuvsDS43r7g9U1WeT/FCSn6uqx3R3T9U5MsnRw+EZQ6C2lFdnZ0D2wCSLw6+fzc7A9FUrtP7qJPcdxv5sJq+RAgAAAOxxRgnHuvs1YzxnM1XVQ5I8IJOZW09cZfiCWyY5dNg/e5WxZ2cSjh2W5IgkX5i6dvyicUvq7gur6twkRya56xJD1lRn0bW7RjgGAAAA7KHGfK1yr1VVN0jywuHwyd198Rpv/eGp/c+sMnb6+tGLru1KnW1VdcAydb7V3RcuV6C7v5rk28v0AgAAALDH2JMWut/KnpvJ1x3fl+SV67hv+muPF6wydvvU/rYZ1Knhvs8uUWe1Ggt1brtEL6taw1cu52YdsyNOO+sa584//YRN6AQAAADm0+jhWFXtk+SeSe6cSQiyf5KnDrORFsZca+jt6u7+7tg9rkdV3S3JqUmuSvKo6bXA1uDAqf1LVxn7nan9621wndVqTNdZXGMttq8+BAAAAGDjjRqOVdUDkrwoyS0WXXp+kq9OHZ+a5MVJLq2qQ7v7O9mChhDvZZnMwvrT7v7kOktcZ2p/tS9bToeE193gOmv5yuZCncU1AAAAAPYYo605VlW/muTNmSwmX0m+PmyX8ook38pkVtIDx+hvF/1ukqOSfCnJ7+/C/VdM7V9rlbHXntq/fIPrrFZjus7iGmuxbZXfcbtQEwAAAGDdRgnHquoHk/zZcPhPSX64u2+63PjuvjLJGzIJz+6z8R2uX1UdleQpw+Fjd3F22yVT+6u9nji9eP7i1x5nXWctr0ou1FnLK5jfp7svWOmXZNmPAQAAAADM0livVT5heNYnk9x/CL9W854kpyS5/UY2thuekMkMq88n2b+qfnGJMbeb2r9XVS0sNP/WIUybXvh+tUXqpxe+X7xm1+I6K30tc6FO55oL71+Q5GZr6GW6jvXDAAAAgD3WWOHYvTIJY16wxmAsSc4btuv+GuJIFl4rvFWS161h/NOn9m+ZyYL2n5o6d9Qq909f//Sia4vr/Osa6mxfYrbbp5LcIcn1q+qQ7l5yBldV3TzJQcv0AgAAALDHGGvNsYWZSB9bxz0Lwc3+M+5lK/lCkq8M+/dYZezdh+2Xk5y/6Np7p/aXrTPMXDtyOHzfEkPWVGfRtaXqAAAAAOwRxgrHetiuJ+i68bD91ox7mYnuPqm7a6Vfvn+R/ntOXTt/qNGZfKQgSY6qqp9Y6lnD+YUZX28e7pvu5dzsnMH1kKpa7r/zSVP7Zy5x/S1Jdgz7Jy9TY7rOjuEeAAAAgD3SWOHYl4ftrdZxz/HD9vMz7mWreUGSq4f9F1fVdacvDscvHg6vGsYv5fnD9kZJnrv4YlXdOjs/IHBelgjHhtco/9dweN+qetASdR6c5L7D4V8v9+olAAAAwJ5grHDsXzL58uQj1jK4qq6f5FGZzDj7p41ra/MNs76eNxwem+R9VfULVXVsVf1CJq8tHjtcf153//sypV6Tna84Prqq/k9V3beq7lhVj0nyfzNZJ2xHksd191XL1HlqkouG/ddV1elVdfzwOz3J3w7XLkrytF34JwMAAABsGWMtyP/SJL+a5B5VdVJ3v3q5gVV14yT/J8khSb6X5C9H6XBzPTXJTZP8SiZf5/zfS4x5ZVYIo7r76qo6McnbkhyX5OeH37TvJnlMd799hTrbq+pnkrwpk7/Bk4fftAuTnNjdi792CQAAALBHGWXmWHd/NMkLM5k99sqqen1VPWRqyF2q6peq6s8yeeXv7pnMGvvD7v7iGD1upu7e0d2nJDkhkzXIvpLkymH75iT37+5Tu3vHCmXS3RcnuUuS38hkcf2vJ7kik1dTX57kDt39ijX088EkxyR5ZpJPJrl0+H1iOHe7YQwAAADAHq0Wre2+cQ+qqiQvSfLr2blA/5JDh+0Luvu3NrwxtpyqOjzJ9iTZvn17Dj/88FXu2DMccdpZaxp3/uknbHAnAAAAsOe54IILsm3btoXDbbN6o22sNcfSE4/OZDH3f8kkIKtFvyR5f5ITBGMAAAAAbLSx1hz7L939D0n+oaoOzGR9rZsm2TeTVwD/dXg1EAAAAAA23Ojh2ILuviTJuzfr+QAAAAAw2muVAAAAALDVbMrMsaq6aZKfzOSLiDcaTn8jky8j/kt3/8dm9AUAAADAfBk1HKuqw5L8cZIHrvDsq6vqzCRP6u4vjdYcAAAAAHNntNcqq+r4TGaGPTjJf8s1v1S58NsvyYOSfHy4BwAAAAA2xCjhWFUdmuStSa6fSQD29kxCslskuc7wu0UmodjbhjEHJXnrcC8AAAAAzNxYM8eekkkwdnWSh3f3Cd39hu7e3t1XDr/t3f3G7n5Akv+ZZEcmAdlpI/UIAAAAwJwZKxy7f5JO8vLu/pvVBnf33yZ5WSYzyE7Y4N4AAAAAmFNjhWMLr0b+3TruWRjrtUoAAAAANsRY4dh/DttvreOehbH/ueIoAAAAANhFY4VjHxm2x6zjnoWxH1lxFAAAAADsorHCsRdlsn7Y71TV/qsNHsY8OZN1yl68wb0BAAAAMKdGCce6+11Jfj/J0Un+pap+bLmxVfWjSf45yQ8l+f3u/ocxegQAAABg/uw3y2JV9YwVLncmr0gem+ScqvpEkg8n+dpw7WZJjsui1ymr6hnd/Qez7BMAAAAAkhmHY0l+L5OgayWdySuWx2TpNchqGHPs8EsS4RgAAAAAMzfrcCyZhFu7O26tNQAAAABgl800HOvusRb4BwAAAIDdJswCAAAAYG4JxwAAAACYW8IxAAAAAObWRizIvyZVdVCSA5Psu9rY7v7SxncEAAAAwLwZNRyrqvsk+fUkd0tywzXe1tnEEA8AAACAvddooVNV/WWSX104HOu5AAAAALCcUcKxqvq1JI8cDi9JcmaSjyX5ZpIdY/QAAAAAAIuNNXNsIRj7dJJ7dfd/jPRcAAAAAFjWWF+rPCqTtcN+TzAGAAAAwFYxVjh26bD995GeBwAAAACrGisc+/SwvflIzwMAAACAVY0Vjr0sky9UPnSk5wEAAADAqkYJx7r7b5O8IcnDquoxYzwTAAAAAFYz1tcqk+RhSZ6f5AVV9YtJzkhybpLLVruxu9+9wb0BAAAAMIfGDMe+l+RjSf4zyZ2H31p0xu0TAAAAgDkxSuhUVfsleV2S/7FwaoznAgAAAMBKxpqR9agkPz/sfzHJazKZRfbNJDtG6gEAAAAAvs9Y4dipw/YDSe7d3ZeP9FwAAAAAWNYoX6tMcptM1g57tmAMAAAAgK1irHDsO8N2+0jPAwAAAIBVjRWOfWzY3mKk5wEAAADAqsYKx/4yky9UnjLS8wAAAABgVaOEY939xkwCsgdU1fOrat8xngsAAAAAKxnla5VV9fBMvlR5+yRPSPKgqnpjknOTXLba/d392o3tEAAAAIB5NEo4luTVmXytcsG2JL+5xns7iXAMAAAAgJkbKxxLJmuOAas44rSzrnHu/NNP2IROAAAAYO83Vjh2y5GeAwAAAABrNko41t1fHOM5AAAAALAeo3ytEgAAAAC2IuEYAAAAAHNLOAYAAADA3BplzbGq+vxu3N7dfeuZNQMAAAAAg7G+VnnEOsZ2klp0DAAAAAAzN1Y49po1jDkgyZFJfiSTQOyjST6xkU0BAAAAMN9GCce6++S1jq2q2yZ5ZZJjkvxRd79xwxoDAAAAYK5tuQX5u/vfkvxUkq8keW1VHbXJLQEAAACwl9py4ViSdPelSf4kyf5JnrTJ7QAAAACwl9qS4djgI8P23pvaBQAAAAB7ra0cji18sfJmm9oFAAAAAHutrRyO3XfYfmtTuwAAAABgr7Ulw7Gq+sUkT0nSSd67ye0AAAAAsJfab4yHVNVfrWHYPklumOTHkxyayWuVVyU5fQNbAwAAAGCOjRKOJTkpk1lga7Gw1ti3k5za3R9ZaTAAAAAA7KqxwrEvZfVwbEeSS5J8IcnZSf6muy/e6MYAAAAAmF+jhGPdfcQYzwEAAACA9diSC/IDAAAAwBiEYwAAAADMLeEYAAAAAHNLOAYAAADA3Jr5gvxVdfWMS3Z3j/VVTQAAAADmyEaETrUBNQEAAABg5jYiHHvNbt5fSe6f5MYRtAEAAACwgWYejnX3ybt6b1WdmOT3MwnGFmzf7aYAAAAAYAlbYkH+qrp/VX04yRuS3C6TGWMXJnlskiM3szcAAAAA9l6butB9Vf33TGaK3WnhVJKvJXlOkr/o7is2qzcAAAAA9n6bEo5V1T2S/GGSuy6cSvL1JM9L8pLuvmwz+gIAAABgvowajlXVXZL8QZJ7LpxK8s0kf5LkBd196Zj9AAAAADDfRgnHqurYTGaK3WfhVJJLkrwgyZ9097fG6AMAAAAApm1oOFZVP5rJTLEHLJxK8p0kL0nyvO7+xkY+HwAAAABWsiHhWFXdNpOF9h+4cCrJ5Un+IslzuvuijXguAAAAAKzHzMOxqnpdkgdnEohVku8meWmS07v7wlk/DwAAAAB21UbMHPuFqf2LkrwoyfYk96mqXSrY3a+dQV8AAAAA8H02as2xHrYHZ7Lm2O7WEo4BAAAAMHMbFY7t2hQxAAAAABjRRoRj99yAmgAAAAAwczMPx7r77FnXBAAAAICNsM9mNwAAAAAAm0U4BgAAAMDc2qgF+YEZOuK0s77v+PzTT9ikTgAAAGDvYuYYAAAAAHNLOAYAAADA3BKO7aaqOraqnlFV76yqC6rqu1V1aVWdW1Wvqqrj11nvflV15lStC4bj+62jxn5V9aiqek9VXVRVl1fV56rqpVV123XUObiq/qCqPl5V3x5+Hx/O3Xg9/y4AAACArciaY7uhqt6d5G5LXLpWkh8cfidV1WuT/Gp3X7lCrX2SvCzJKYsuHTb8TqyqVyT5te7esUKdg5O8Lclxiy7dKskjkzyiqh7T3a9Y5d92pyRvSnLIokvHDL9Tq+rE7v7QSnUAAAAAtjIzx3bPocP2K0lemORBSe6Y5M5JfivJl4frD0/y6lVqPSs7g7GPJnnoUOuhw3GSnJrkmcsVqKp9k5yZncHYG5PcL8mdkjwuydeSXDvJS1eaiVZV25K8NZNg7Kokz01y9+H33OHczZO8taoOX+XfBQAAALBlmTm2ez6T5HeTvKG7r1507QNV9ddJ3pfkyCQPraq/7O53Ly5SVUcmeeJw+JEkd+/uy4fjD1fVW5KcneTYJE+qqr/q7vOW6OcRSRZe4/zz7n701LUPVdXbk5yT5KAkL6qqo7v7qiXqPCvJTYb9X+ruv5u69p6qOifJ65PcNJOw7qQlagAAAABseWaO7YbufkB3n7FEMLZw/eIkvz116kHLlHp8dgaVj50KxhbqXJbkscPhfkmesEydhYDtG0metEQ/5yV59nB4myQPXDymqg5J8rDh8B2LgrGFOmckecdw+MvDPQAAAAB7HOHYxvvnqf1bL75YVZXk54bDz3T3B5YqMpz/7HD4c8N903WOTHL0cHjGEKgt5dVT+9cIx5L8bHb+f/GqZWpM19lnuAcAAABgjyMc23jXntpfaobZLbNz7bKzV6m1cP2wJEcsunb8EuOuobsvTHLucHjXJYasqc6ia0vVAQAAANjyhGMb7x5T+59e4voPT+1/ZpVa09ePXnRtV+psq6oDlqnzrSFIW1J3fzXJt5fpBQAAAGCPYEH+DVRV+yQ5berUGUsMm/7a4wWrlNw+tb9tBnVquO+zU9cW6qxWY6HObZfoZUVr+MKlNcwAAACAUQgld2LxAAAgAElEQVTHNtYTktxx2H9jd5+zxJgDp/YvXaXed6b2r7fBdVarMV1ncY3VbF99CAAAAMDG81rlBqmqeyQ5fTj8WpJfX2bodab2r1yl7Hen9q+7wXVWqzFdZ3ENAAAAgD2CmWMboKpum+TMTP77XpHkwd39tWWGXzG1f61VSk8v7n/5KnWuyPJWq7P/GnqZrrO4xmpWew3zkCQfXmdNAAAAgHUTjs1YVd0yyTuT3DCTr1P+Yne/e4VbLpnaX+31xOnF8xe/9ri4zkrh2Gp19l9DL9N11vIK5n/p7hXXM6uq9ZQDAAAA2GVeq5yhqjo0ybuSHJqkk/xKd795ldumg6LVFqqfnnG1eN2uXanTuebC+wvHq9WYrmMNMQAAAGCPJBybkao6OMk/JLnVcOqx3f3aNdz6qan9o1YZO3390zOos727v7Po2kKd61fVsl+NrKqbJzlomV4AAAAA9gheq5yBqrp+knck+eHh1Gnd/WdrvP0LSb6SyWyze6wy9u7D9stJzl907b1T+/dI8r+X6fWQJEcOh+9bYsh7k/zyVJ3XL9PLdK9L1WEDHXHaWdc4d/7pJ2xCJwAAALBnM3NsN1XV/knOSvLjw6lndfdz1np/d3eShVcvj6qqn1jmOT+RnTO+3jzcN13n3OycwfWQoa+lnDS1f+YS19+SZMewf/IKrS/U2THcAwAAALDHEY7thqq6ViYB012HUy/s7qftQqkXZLJ4f5K8uKquu+g5103y4uHwqmH8Up4/bG+U5LlL9HvrJE8ZDs/LEuFYd1+Y5H8Nh/etqgctUefBSe47HP71cA8AAADAHsdrlbvndUnuM+z/U5JXVtXtVhh/5TDD6/t097lV9bwkpyU5Nsn7quo5ST6X5NZJnpzk9sPw53X3vy9T/zVJfiWTsO7RwyuUL0/yn0numOTpmawTtiPJ47r7qmXqPDXJTye5SZLXVdWxSf5+uPaAJL897F+UZFfCQAAAAIAtQTi2e/7H1P69knx8lfFfTHLEMteemuSmmYRbt8/Sa4a9MiuEUd19dVWdmORtSY5L8vPDb9p3kzymu9++Qp3tVfUzSd6U5JBMwrknLxp2YZITu3vx1y4BAAAA9hheq9wiuntHd5+S5IRM1iD7SpIrh+2bk9y/u0/t7h0rlEl3X5zkLkl+I5PF9b+e5Iokn89kFtkduvsVa+jng0mOSfLMJJ9Mcunw+8Rw7nbDGAAAAIA9lplju6G7awNqvi2TmV+7U+OqJH8x/HanzsWZvIr59N2pAwAAALBVmTkGAAAAwNwSjgEAAAAwt4RjAAAAAMwt4RgAAAAAc0s4BgAAAMDcEo4BAAAAMLeEYwAAAADMLeEYAAAAAHNLOAYAAADA3BKOAQAAADC3hGMAAAAAzC3hGAAAAABzSzgGAAAAwNwSjgEAAAAwt4RjAAAAAMwt4RgAAAAAc0s4BgAAAMDcEo4BAAAAMLeEYwAAAADMLeEYAAAAAHNLOAYAAADA3BKOAQAAADC39tvsBoDZOOK0s65x7vzTT9iETgAAAGDPYeYYAAAAAHNLOAYAAADA3BKOAQAAADC3hGMAAAAAzC3hGAAAAABzSzgGAAAAwNzab7MbADbOEaeddY1z559+wiZ0AgAAAFuTmWMAAAAAzC3hGAAAAABzSzgGAAAAwNwSjgEAAAAwt4RjAAAAAMwt4RgAAAAAc0s4BgAAAMDcEo4BAAAAMLeEYwAAAADMLeEYAAAAAHNLOAYAAADA3BKOAQAAADC3hGMAAAAAzC3hGAAAAABza7/NbgAY1xGnnXWNc+effsImdAIAAACbz8wxAAAAAOaWcAwAAACAuSUcAwAAAGBuWXMMuMY6ZNYgAwAAYF6YOQYAAADA3BKOAQAAADC3hGMAAAAAzC3hGAAAAABzSzgGAAAAwNwSjgEAAAAwt4RjAAAAAMwt4RgAAAAAc2u/zW4A2HqOOO2sa5w7//QTNqETAAAA2FhmjgEAAAAwt4RjAAAAAMwt4RgAAAAAc0s4BgAAAMDcEo4BAAAAMLeEYwAAAADMLeEYAAAAAHNLOAYAAADA3NpvsxsA9lxHnHbWNc6df/oJm9AJAAAA7BrhGLAmSwVhAAAAsKfzWiUAAAAAc0s4BgAAAMDcEo4BAAAAMLesOQbMlEX6AQAA2JOYOQYAAADA3BKOAQAAADC3hGMAAAAAzC3hGAAAAABzy4L8wIZbvEi/BfoBAADYKswcAwAAAGBuCccAAAAAmFvCMQAAAADmljXHgNEtXoMssQ4ZAAAAm8PMMQAAAADmlnAMAAAAgLklHAMAAABgbllzDNgSllqHbCnWJgMAAGCWhGPAHsVi/gAAAMyS1yoBAAAAmFtmjgF7vLW8kml2GQAAAEsxcwwAAACAuSUcAwAAAGBuCccAAAAAmFvWHGNFVXWLJI9LckKSbUm+m+RzSc5I8mfdfdkmtgdrttavXPoaJgAAwHwRjrGsqvqZJH+T5KCp0/snOXb4nVpVJ3T3eZvRH+yutSzkv9Q4YRkAAMDew2uVLKmqbp/k9ZkEY5cmeWqSuyS5d5KXD8OOTHJWVR24KU0CAAAA7CYzx1jOC5NcN8lVSe7T3e+fuvZPVfXvSZ6bSUD220l+b/QOYQtZ6yw0s84AAAC2luruze6BLaaq7pjkg8PhS7v7UUuM2SfJJ5McneSbSW7a3d+b0fMPT7I9SbZv357DDz98FmU33VrDE+aPwAwAAGB1F1xwQbZt27ZwuK27L5hFXa9VspQTp/ZftdSA7t6R5LXD4Q2S3HOjmwIAAACYNa9VspTjh+13kpyzwrizp/bvmuSdG9YR7MVmOatwV2eh+UonAAAwr4RjLOXoYXted1+1wrjPLHHPqobXJldy2MLOV7/61bWW3fKu+vbFm90Cc+Dw33jNzGpdcME1Zyj/xB/945ru/cDv3nvVMUvVWst9AADAfFqUEew7q7rWHOP7VNV1klw+HJ7V3Q9YZfylSQ5I8oHuvvMan+F/OgAAAGB3HNfdH5lFIWuOsdiBU/uXrmH8d4bt9TagFwAAAIAN5bVKFrvO1P6Vaxj/3WF73XU8Y9sq16+V5KgkX0tyUZKr11F7sx2S5MPD/nFJLtzEXpg9f9+9n7/x3s3fd+/m77t38/fdu/n77t38ffduY/99901yk2H/E7MqKhxjsSum9q+1hvHXHraXrzhqyho/tfr5tdbbSqpq+vDCWX1Wlq3B33fv52+8d/P33bv5++7d/H33bv6+ezd/373bJv19vzjrgl6rZLFLpvbX8qrkAcN2La9gAgAAAGwpwjG+T3dfkeTrw+GKX5WsqhtmZzi2fSP7AgAAANgIwjGW8qlhe5uqWunV26Om9j+9gf0AAAAAbAjhGEt577A9IMkdVhh3j6n9921cOwAAAAAbQzjGUt40tX/yUgOqap8kDx8Ov5nknze6KQAAAIBZE45xDd39oSTvGQ5Pqao7LzHst5McPey/sLu/N0pzAAAAADO00npSzLffzORVyesmeWdV/VEms8Oum+QXkzxyGHdukj/elA4BAAAAdlN192b3wBZVVT+T5G+SHLTMkHOTnNDd543XFQAAAMDsCMdYUVXdIpNZZCckOTzJlUnOS/J3SV7S3ZdtYnsAAAAAu0U4BgAAAMDcsiA/AAAAAHNLOAYAAADA3BKOAQAAADC3hGMAAAAAzC3hGP+vvfsMl6Qq1z7+v2FIQ0aCJB0UEYegAwgSJAjoiyAigiKiDBkEBAO+4hEJKucgB0VBUBh0QNBDkigoIkGiEhWJgo5kYcjMkHnOh7X6dE1P5669e+/d9++66uqqrlXVq7tqdVU/vYKZmZmZmZmZ2cBycMzMzMzMzMzMzAaWg2NmZmZmZmZmZjawHBwzMzMzMzMzM7OB5eCYWUkkvV3SMZLukTRD0tOSbpJ0kKTx/c6fzU7SWpK+JekySQ9LekXSi5Luk/RzSRu0sY/JkqLNafIwvC3LOjguV7Wxry0knVc4Tx7Oy1sMw1uxGpKu6uD4VqaNa/bhstsnkpaUtJWkIyRdKml64bOe2sX+ei6fksZJ2lvSNZKelPSSpAck/VTSKp3madCVcYwljZe0raQT8/3UM5Jek/SUpBskHSbprW3sp+3vi57f+IAo6fiW+h2cz5ev5XPlaaV78XuU7s3f3ut7HiS9Hl9JE7q4Rk9rsC+X35KphN8/NfsbM9fgccP1QmZjmaSPAacDCxWeHg+slafdJW0ZEff3I382O0l/BD5YZ9XcwLvyNFnSacAeEfHqcObPRgZJcwAnAbvVrFo2T9tImgLsFRFvDnf+rG1vAn/vdybs//y7jJ2UVT4lLQ5cAry/ZtU7gD2BnSXtFxFTysj3gOjpGEtaHbgOWKDO6sWAD+TpS5L2jIgze3k961gpZbgsklYkleF31ax6d552l/TZiLh42DM3OvXj+N7bh9ccOGX+/hmL12AHx8x6JGkScCYwH/Ai8J/AlXl5B2APYCXgN5LWiogX+pVXm8Uy+fFR4GzgGuBBYE5gXeArpC/2zwNzATu2sc+P5P018nC3mbWenAic0GT9jCbrvkv1on8b8D3gAeCdwNeAScDuwJPAN3rOqbVrF2D+Fmkmkr6bAf4QEY80Seuy2z8PAvcAH+5i257Lp6Q5gfOo3pT/GjgZeBpYB/gmsCTwU0mPRMSlXeRz0HVzjBeiGhi7DrgYuBl4ClgC2JZ0f7UQcIak59s4NjeTvjusXL2U4Yquv4MlLQj8hmpg7GTgf4CXgE2Ag0nnyZmS1o+I23vI5yDq5vg+AqzWRrqDqd5fn9oirctvOcr8/TP2rsER4cmTpx4m4I9AAK8B69ZZf1BeH8Bh/c6vp/87LhcDnwLmbLB+cdK/WJVjt2GDdJMLaSb0+315muXY9FTuSEHt1/I+bgLmq1k/Pj9fKf8r9vs9e5rl+BxVOAd2qrPeZbd/x+ZwYCtgqbw8oXAspra5j1LKJ7Br4bV/XGf9isBzef3fgXH9/vxGw9TrMQbWIwW3JzZJ83FSrdAA7gfUIN1VOc1V/f5cxspUUhku5TsYOKKwn4ManEuv+RwY3uPbxmvMSQqiBfB87Xd4IZ3Lb7nHtqzfP2PyGuw+x8x6IGltqlVTT4mIG+okOwa4O88fIGmuYcmcNRURW0XEWRHxRoP100n/nlRsNzw5sxHkQKo1rPePiJeKKyNiJrB/XhwHfGkY82ZN5Kr+n82LL5L+ibQRIiIOjYiLI6KXpjtllc+v5senSX9m1eb1flKNcEg36Z/oIc8Do9djHBHXR8SnI+KuJmkuoFq230mqpWDDoKQy3LN8T/3FvHg36Z57FhFxPXBKXtxIUm3TLasxTMd3M6q1mM6p/Q63oVHi758xeQ12cMysN9sU5n9eL0GkNtan5cVFSFW8bXS4sjD/zr7lwoadJJFqJQDcExE31kuXn6/0k/HxvJ3136akZgGQbrpn9jMzVq6yyqeklYD35MWzmpwnUwvzDo6NLL5OD7ZNgIXz/KnRuF+jqYV5l+GR4fOF+VZNKm14Nf1eHcvXYAfHzHpTGc1jBnBLk3RXF+bXH7rsWMnmKczX/YfFxqwVqP6jeXWzhIX1y5KaHlj/FW+6T2uYykarssrnBnXSzSYiHgfuy4u+ho8svk4PtrbKMKm/qsoPb5fhPsv9xFUqGEwjdVFjI0er79Uxew12cMysN5Vo9/0R8XqTdPfU2cZGvo0K83c3TFX1c0mPSno1D3t9o6TvSFq29aY2hLaXdJekmZJekPR3SadKalaLc2Jh/p6GqWZf7/LdZ5IWoPrP4r9I/ZW04rI7upRVPrvZz/KSWg0GYcOnk+v0ypL+JOlZSS9LeljSBZI+7y4v+q7b7+C2ynC+R6+MGO/rdP9tR+qTCuAXkTuXasHld/i0+l4ds9dgB8fMuiRpXlKnhdBiJLOIeIbqiHjLD2W+rBy5z6KvF546q43NNgaWJo3u8hbSKCv/Adwvaa+y82htm0i6IM9HGv1sRVLNoisknSdp4TrbLFeYbzVS4UOFeZfv/vsk1ZEsT2/zpntjXHZHk7LKZzf7Uc121ieS3gtsmRfviIhWwbGlgLVJzfDmIdVk2JrUpOt2SQ6a9M/GdPcdXCmLMyLi2RavUSnDS0iap2lKG2rd1O52+R0Gbf7+GbPX4HGtk5hZAwsW5l9sI/0M0g+2BVoltBHhS6SLMMCvI6JZs9l/kDoFvoHql/c7SD/StwPmBX4iKSLipCHKr81uJnAh8AfSP04vAkuQ/hHbm3QDvg1wgaTNI+K1wradlO8ZhXmX7/7r5KbbZXd0Kqt8upyPUjm4MYU04h2kQEojb5KuA5cAfwGeIh37NYC9SH+eTASulLR2RDw4VPm22fT6HVwpw+3eh1csALzSVY6tJ5LeRrVm0vW5w/VmXH6HVzu/f8bsNdjBMbPuzVuYf7WN9JWL8HxDkBcrkaSNgP/Ki08A+zRJfh6pE9ja2ik3AWdK2op04zcX8ANJF+a28zb0lm3wT/LvJR0HXEoa3Wwj0jH+USFNJ+W7eIPt8t1HkpYj1UAAuDEi7muS3GV39CqrfLqcj17HA2vl+VMj4qImabdtcC24RtIJwMnAzqSaKccC25aaU2ukjO/gShnu5D4cXIb7aSdS7R9or9aYy+8w6eD3z5i9BrtZpVn3Xi7Mz91G+koVbg9VPIJJWoV0wzaOdIy3j4gnGqWPiOeaNduKiIuBI/LieGC3ErNrTTRrYpGHJ98OqNQW278mSSflu9g8w+W7v3aiem/TdPQrl91Rrazy6XI+Ckk6GNg9L94E7NssfYtrwWt5X5UR1T7hvgaHR0nfwZUy3Ml9OLgM99Pn8uMrwJmtErv8Do8Of/+M2Wuwg2Nm3XuhMN9O9c5KHzjtVP22PpC0AnAZsChpdJYdIqKMEXROAio3gBs1S2jDJyL+Afw+L64oaZnC6k7Kd7FjUJfv/uroprsNLrsjU1nl0+V8lMn9Tx2ZF+8BPhoRM5ps0lLurP2UwlMu6yNHq+/gShnu5D4cXIb7QtLawMp58cI2+olryeW3d138/hmz12AHx8y6FBEvk9q9Q4uOASUtSrVQP9QsrfVHDoxcThqaOIBdI+KCMvad/3mpnCv+R2tkuaswXzw2xY5BW3X8Wexg1OW7TyStRXXko4vzQCg9cdkdscoqn93sJ2jdcbANAUmfAU7Ii/8CNo+I6SXtvtG1wPqoje/gSlmcX9IiLXZXKcNPRoT7G+uPbjrib4fLb5e6/P0zZq/BDo6Z9abyZbyipGZ9+K1cmG81mpINM0mLk2oQvSM/tX9ElHnRhuo/nzayNDouxRutlRukqbfe5bt/ijfdTZtUdshld+Qpq3x2s5+Heq2pZJ2TtDXpx/QcwGPAphFR5g8kl/ORq9mxaasM53v0d+ZFX6f7QNJcwA558QngtyXu3uW3Cz38/hmz12AHx8x6c21+nB9Ys0m6YhXf64YuO9YpSQsDv6Na4+TrEfHjkl9jCWDxvPhomfu2nk0szBePzT8Ly62q6G+YHx8BppWTLetEzU33k6TBFsrYr8vuyFRW+by2MN9wP5LeCqyUF30NH2aSNgXOIvWF8xSpxtgDJb9Mo2uB9VEb38FtlWHS4A2VFhwuw/2xJWmUcIBf5uaQZXH57VCPv3/G7DXYwTGz3pxfmN+lXgJJc1Ct0fAscOVQZ8raI2k88BvScNAA342Io4bgpfakOjLP1UOwf+tC7mNh87z4QEQ8UlmXOwmuVCtfWdIHGuzjA1T/zbqgWefCNqS2AJbI82XedLvsjkBllc88mmnln+xP5WtCPZML8+d1lWnriqT1SMd6HuA54CMRcWfJrzEO2LXwVBl9jVo5Wn0HX0U6LwB2lqQ6acBleCQYktrdLr+d6/X3z1i+Bjs4ZtaDiPgzcE1e3E3SunWSfQV4T57/YR5ZxfpM0tykL9j181M/jIhvdriPCZImtUizFfCtvPgS8PNO82qdk/SxZk2dJS0FnEt1dJwT6iQ7ltQxKcBxkmYZOjovH5cXX8/prT866sfEZXdMKKt8/nd+XAz4Xu1KSe8EDs6L9+Mf1sNG0vtIP+DmB2YAW0bELR3uY5NmfVHlWqdTqN6nXRQR7jtyiJX1HRwRrwI/yovvAb5aZz/rUh3p8uqIuKnbfFt3JC1GqjkGcEdE3N7mdi6/JSvj9082Jq/BzfpIMrP2HECq4jkfcJmkI0m1w+YjNfPZM6e7DzimLzm0en4FfDjPXwGcImnVJulfzf9wFE0ArpR0A3AR8BdSPwqQ2u9vl6fKP5lfLdZOsiF1HDCXpHOBG0hVuV8iNc/YGNiLalONa4HZqpJHxH2Sjga+TmqScZ2ko4AHSH2X/H+gcnN/dET8fajejDWWBzzZKi/+LSJubWOzCbjs9o2kDYAVC08tXphfUdLkYvqImFq7jxLL56mkWgfrA/vm5hsnA88AawOHAAsBbwJfLLkp0JjV6zHOP4h+B1R+GH8TeK7FdfqJ3IF70c7AhZIuJNUyuhd4njQy2pqke7RKs6InSPd01kIJZXgC5X0HHw18mtTs6nuSVgT+h3TN3wT4Buk370vAgW29wQFXxnd0jR2o/hnZSa0xl9/ylfH7Z+xegyPCkydPPU7Ax0jVuqPBdC+wYr/z6WmWY9boWDWaptXZx8ZtbjsD2LPf73mQJlIwrJ1jcw6wSJP9zEEaIrzZPqYAc/T7PQ/qBOxdOBYHtbmNy25/j9nUTr5/m+ynlPJJ+uH35yb7eBnYvd+f22iaej3GpGY0nV6nD+shH38FJvb7cxstUwnHt9TvYFIg574m+3kO2Krfn9tomcr6ji7s78ac9nXgrUOQD5ff9j/TTr9XpzXZ15i7BrvmmFkJIuIiSauT/rHYkjQc7auk6p9nA8dHxMw+ZtGGxi3ATsC6pH9NliZ9wY8j/eNxJ/AHYErM/m+2Da2dSZ17rkv6F3px0j9PL5KGkr4eODUibmi2k4h4k9Rk+lzSP5Tvz/uaDtwE/DQiSun83br2ufz4BnBGm9u47I4BZZXPiJie+7baA9iR1ERnflKHw38gNTsptZ8rGzZHAbeTyvpEUt+EiwGvAP8Gbib9SXJeRLzRaCdWulK/gyPi/txMc19ge1KwbG7S9f4SUhn+1xC8D2tB0ruAdfLi7yPi8Q42d/kdwcbiNVg5WmdmZmZmZmZmZjZw3CG/mZmZmZmZmZkNLAfHzMzMzMzMzMxsYDk4ZmZmZmZmZmZmA8vBMTMzMzMzMzMzG1gOjpmZmZmZmZmZ2cBycMzMzMzMzMzMzAaWg2NmZmZmZmZmZjawHBwzMzMzMzMzM7OB5eCYmZmZmZmZmZkNLAfHzMzMzMzMzMxsYDk4ZmZmZmZmZmZmA8vBMTMzMzMzMzMzG1gOjpmZmZmZmZmZ2cBycMzMzMzMzMzMzAaWg2NmZmZmZmZmZjawHBwzMzMzMzMzM7OB5eCYmZmZWQckRZ4O63deRipJc0o6QNKfJT1f+MzO73fezMzMzGo5OGZmZmZtkbRxIcgRks5sY5uplfTDkUcbMX4FHAu8H1iwz3kxMzMza8rBMTMzM+vW9pJW63cmbGSRtB6wfV78DbA5sDqwGvDFfuXLzMzMrJFx/c6AmZmZjVoCDge27XdGbETZLD++AewYEc/3MzNmZmZmrbjmmJmZmXVjen78hKRJfc2JjTTL5sd/OzBmZmZmo4GDY2ZmZtaNHwGv5Pkj+pkRG3HmyY+v9TUXZmZmZm1ycMzMzMy68RBwUp7fStLa3exE0rTcYf/UFukqHftPq7NuQmGQgMn5uW0lXSbpCUkzJP1F0v6S5ipsJ0k7Sroqp5sp6VZJe0tSB+9hM0kXSnpM0suS/iHpeEnLtt4aJK0h6SeS7pX0Ys7vvZJOlLRSk+0mF973BEnzSDpQ0o2Spvcyoqak1SSdJOnv+XN5QdKdkn4gaUKDbSoDL+ycn3p7zQAOXQ3KIGluSV+QdKWkJyW9KulxSZdI2klSW/ezkj4q6fR8fGbkY/VPSefmz3J8k21XlXScpDskPSPptZyHyyV9TdLSNemLg1ds3CJfDUc/lXRY8bOTtLCkQyTdJunZmnO+7bQ1r7GNpLMlPZg/k2cl3SzpUEmLNsn3LGVS0iKSjsjnyYy8nz9K+myz91/Y34KSviLpivzZvqo00ult+bNfv8m2c0raWdLFkh6V9IqkpyRdK+nLkuZr8dprSjpF0n2Fc+MhSbdI+rGkraX2vxPMzGz0cZ9jZmZm1q3/BHYH5gO+DXykv9lJJJ0A7FPz9Oqk2m4bS/oU6R7odGC7mnSTgBOBNYA923itQ4HDap5eAdgX2EnSxyLimgbbzgH8N3Agqf+2opXytLukfSPipNrtaywOnAe8r1WeW5F0MPAdZv8TdWKe9pG0Z0Sc1utrtZGXCcClwMo1q5YCtsjTXpI+HhFPN9jHW4AzgU3rrJ6Qp0q/eVNrtp0TOJr6x2ipPG1K+lwmt3o/vZD0LuAyUn57TpsDX+cAH6pZNQ+wZp6+kD/bG1u83ruB39Z5vQ8CH5S0bkTs12T7zUgjnC5es2ou0jn9PmA/Zj8GSHobcCHw3ppViwHr52kfSVtGxH11tv8SqRzWnu/L5WkN4AukUVdfbPQezMxsdHNwzMzMzLoSEY9JOhH4MvBhSRtExLV9ztbewDrAJcAU4F/A8sDB+fltgV1IwbLtgF/m6THgXaRA18rAHpJ+HRG/bfJaWwJrAfcC3wP+CixMGqlxjzx/saRVI+KhOtsfR/rRDfBHUmDmH8BM0g/9A4FVgJ9KejwiLmySl1NIo0GeRgoEPQ68jWrT17ZI+gJwZF58EjgKuA6Yk9TR/kHA/MBUSdMj4pLC5pWRS78DfBx4lB4CppIWAP4AvCM/dT7ws7zfFUjBko2ADYCLJG0YEW/U7GM8cGUhb7eQajz+jfTZLA9sCHy6QTZOAnbN848BxwPXA88BSwBrM3uAdaicQ+rP7ThSMOgZ0sjg+30AAAzGSURBVDn7r07TSpoHuJwU+HmDVAYuAf5JCkhtSCrXSwKXSJoUEfVeB2A8cBHwFtKxv5wURJoEHEoKMO0r6aKI+F3txpI2IQVAx+W8/AK4AHgQmJcUeNwC+Fidbd8CXEs6jq8AJwNXA9OABYAPAwcAKwKXSlojIp4rbL861cDYP0nH93bgaVIw7N3AJqTz2czMxrKI8OTJkydPnjx5ajkBGwORp8n5uSVJP4QDuKLONlMr2zTY57S8fmqL167sZ1qddRMK+QrgB3XSjC+81nTgTeCAOuneCjyf013QIC/F17oFWKBOms8V0pxVZ/3mhfW7NXideUnBoch5H1ezfnJNXurup4PjuwQwI+/rEWD5OmkmFY73w8BcnRyrDvNzdOG9fbvOepFq/1XS7FMnzfcL648H1OC15gaWqnlu68K21wOLNMnr8jXLxbKycYv3WUl3WJ11hxXWvwF8uMl+Okn73ZzuGWDNBmneTgpEBnBGk+McwLPAKnXSrAi81Kg85XP8kbx+RrPPqsH5eEahfKzQYLviOfvdmnVH5OdfrD3+NekWBubo5Xz25MmTJ08je3KfY2ZmZta1iHiCFHQA2CTXAumnh4Cv1T4ZETOBU/PiW4A/RcQP66R7nNQ8EVKTsFb2jIjZmlpFxC9ItWEgjej51pokX8+P50bEKfV2HBEvk2pHQQpUNPtsr2i0nw7sQgoiAnw56tR2i4jbSM1pIdVM2qbH16wr12zaPS/eyexNV4mIINW8eyo/NUuzPUmLAHvlxVtIwdC6/Z5FxKsR8e+apyvHaCawXUQ82yi/9T6rITA1Ii7rNW2ukbdvXjwkIm6ply5STbFv58XtJc3f5PUOiYg76+zjflKNP0g1/Gp9Hlgmz38jIq5q9AK1n3Fuclup8bdfRPyzwXa3AT/Oi5NrVlfK5X11jn9xH89FxJuN1puZ2ejn4JiZmZn16mjghTz/7WYJh8GvI6LRKIl/Kcyf2WQflXSL5gBLI3c0CixkP8uP40g1iQCQtFBh+Zwm2xMRd5NqugGs2yTpGc3206bN8uOzwK+bpJtSZ5uyrQlUPvupUdNcsiIingfOyosTazrG/xDVYN+PGu2jntxc7wN58cyIeLTtnA+dTo5xs7QbkWpCQYvzj9TcF1JTyzUbpAlSs8xGKmVksTrlaav8OIPUJLITW5Ka+86kGohupPI+lsl9lFU8lh8nqstBRczMbGxwcMzMzMx6EhFPAcfmxfUl9bNj/tk63C4o1vxpN92CTdLd1CIvfy7Mr1aYn0T1HuxXqhnRsXai2kl5be2zor+2yEs7Vs2PtzYJMJJr2Eyr2aZsxf3+qUXa4vridpMK83UHRWjifVQ7f+9026HSyTFulnatwvxjLc69vxXSNjr/pufvgEaKAyXUlqfKMbol1+7sROV9jAdeb/E+Li5sV3wfvwJeIw1CcJ2ki5RGq13Vo1OamQ0WB8fMzMysDN+nGlQ6vI/5aPYDu9gsqt10czZJ90SLvBSbaS1WmF+yxXaNjG+y7pku91lUyWOr9wWpw//iNmUr7rdVfh4vzBe3K458+Bid6WXbodLJMW6Wtuzzr1VQq1l5qnzO3XzGPb+PiLgH+Azp8xpHqsl2InAH8ISkX0hqp3m1mZmNch6t0szMzHoWEc9K+j6pg+t1JG0VERe32m6Uq9t/VRuKAYK9SJ29t6NZwKPtJoNt6PZ9DZWRlp++6KRZaIu0xfNvDVLNqXY83O7rD5PK+5hO8/74as3SN1lEnCvpclL/ZR8h9TW4BClwtxOwk6RTgV3d75iZ2djl4JiZmZmV5VjgAFKH94cza1OmRio/NlvVZm/WGXi/LNXB+mLTsmITtJkRUWy61k9PA0vT+n1BtWna001T9ZaXiqVo3gy22EyuuN30wvzS1ARFWqjdtlPFIErDc7tFJ/dDpXj+PRkR/Qx6TQeWo7vPuPI+FgTu7iR4WCsingNOyhOS3gN8HNifNGDAzsBtwGyDeJiZ2djgZpVmZmZWioh4gdQ5P8Aakj7RxmaVjvwXbZFupa4zNnTe38H6YgDsdqq1odYvNUe9qeRxDUkN/0CVtCRp9MziNkOVF4B1WqQtdqRe3O7WwvyGHb7+bVSPUafbQvW8hubndj/O69sK8/0+/yrHaC1JzZoN11N5H/Mwaz9qPYuIuyPiv0iDMszIT3+qzNcwM7ORxcExMzMzK9PxVPuIOpxqp+aNVGrzrNGoA2xJqwCrl5O9Uq0maVKT9bvmxzeAqypPRsSTwI15cUdJSwxN9jp2eX5cBNi2SbrdqB7Xy5uk68UtVPuw21lS3XtWSQtSDVrcFRHFvquupBrY2F9Ss/7jZhERT1Nt7vopScu0nfNkWmG+WeDmMx3utwyXU+0n7It97nj+ovw4Htizi20rAcwDS8tRQUQ8RLXW4uLN0pqZ2ejm4JiZmZmVJiJmAEflxdWAj7bY5Or8uAx1AgU5+HFKaRks30n1msZJ2pHqez+/JmgD8J38uBBwjqRFGr2ApHkk7Stp3lJy3NjPqQZNjpG0bJ28vBf4Rl58BDh/KDISEa8AU/LiqsAhdfIiUjC2ErQ4vmYfzwI/zYtrAsc2CcDOlWvEFVXO4/HA2ZIWbpRfScvVvPYzVEeM3EXSbAMXSNqA1Ax5WOXPpfJZrQf8oFHwEUDSUpJ2H6LsnE46jwC+K2mjJvmo/YzvBc7OiztI+nKzF5K0gqTP1Dy3TYuytzywcl7spFmumZmNMg6OmZmZWdlOpDr6XKvaFqcDz+f5UyR9S9I6ktaWtA+p2dV7mbUp2EhxM6lW0M2SJktaU9KHJJ0A/CKneQH4au2GEXEJ1f6LNgTulnSopE0lvU/S+pJ2ljSF9FkezxD3FZtrtB2UF5cDbpF0YD4W60n6FnAtsACpxs6eEdFuZ+7dOAL4R54/TNI5kraUtIakTwJXAJ/P628g9xdV4xDSyIMA+wE3SdpD0gfyfraWdDQp8DFLIDciLqIamF0PuEvSwZI2zMdoM0lfl3Qb1WBn0Y/z41LANZJ2kDQpH+Pvk2pw3dzhZ1KWbwF/yvMHALfmAOz6+b1tImk/SecDDwJ7D0UmIuJl4HPA66Qg5OWSfpaPyxqS1pW0i6SzgQfq7GIfqufIMZKulrRbPr6T8jH6iqTfA/cDn6zZ/kDgEUlnSdpb0kaF938QcB0wX077k5LfvpmZjSDukN/MzMxKFREvSToSOK6NtE/mWim/AuYlNcU8vJDkJdKP562AZk0Y++E3eTqUVOuq1vPA1hExrcH2XyJ1IH8IqVP5w5q81gzKHZGyrog4Idek+TYpqPODOsleIQXGLhnivLwgaVPgUlLtnU8ye3ADUgBj63odskfETEkfAs4lBSHXpH4QrZG9SOfgvqTajUc2SPeXOs9NAbYAtgEmks7xojtI76e2VuGQi4hXJG0OTCU1oX0vNTXvajzfZF2veblS0lakz2dRYJc8tbPt05LWB84ijTK5Ic37iKv3PsYD2+epnjeBQyNiSGpJmpnZyOCaY2ZmZjYUTgYeaidhRJxNqplzHvAk8Gre9lTg/RFxzlBlslcRcRjw/0hBsn+T8j4NOAFYJSKubrJtRMQRpE7Zv0eqRfQ0KQj2AnAXcAZppLylI+KlIXsjs+brSFIg8mRSbZ2XSMG5u0m13VaOiNOGKS/TSIGb/UhNcJ8CXiN91r8lBU43zH2ENdrH9IjYiBQEOgd4mBTge5lU6+hs4LPMHrwiIt6IiP1JNQRPIvU/NSPn4XHgMuDL1K8d+CawHSmwdlPebgapueV/AOtExOOdfB5liogXIuKTpKDSFOBe0nn3Ouk8vIlU++2jwOZDnJffAe8gNdm9nnSc3yAFs24ljYS7doNtH4+IDUkB9DNIx3Qm6Rg9mfd3DLBRROxas/lnSH2d/ZI0UMbjpPf/InAnqRbspIioVzPQzMzGEEVE61RmZmZmZmZmZmZjkGuOmZmZmZmZmZnZwHJwzMzMzMzMzMzMBpaDY2ZmZmZmZmZmNrAcHDMzMzMzMzMzs4Hl4JiZmZmZmZmZmQ0sB8fMzMzMzMzMzGxgOThmZmZmZmZmZmYDy8ExMzMzMzMzMzMbWA6OmZmZmZmZmZnZwHJwzMzMzMzMzMzMBpaDY2ZmZmZmZmZmNrAcHDMzMzMzMzMzs4Hl4JiZmZmZmZmZmQ0sB8fMzMzMzMzMzGxgOThmZmZmZmZmZmYDy8ExMzMzMzMzMzMbWA6OmZmZmZmZmZnZwHJwzMzMzMzMzMzMBpaDY2ZmZmZmZmZmNrAcHDMzMzMzMzMzs4Hl4JiZmZmZmZmZmQ0sB8fMzMzMzMzMzGxgOThmZmZmZmZmZmYDy8ExMzMzMzMzMzMbWA6OmZmZmZmZmZnZwPpfhUTXbnKBL7IAAAAASUVORK5CYII=\n" - }, - "metadata": { - "needs_background": "light" - } - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "**Additional exercises**" - ], - "metadata": { - "id": "GHHalBbyzilj" - } - }, - { - "cell_type": "markdown", - "source": [ - "1.4) Create a bar chart with matplotlib that shows the frequencies of the five most common AGIs." - ], - "metadata": { - "id": "SiMOd0XEzqoi" - } - }, - { - "cell_type": "code", - "source": [ - "from heapq import nlargest\n", - "\n", - "\"\"\"\n", - "Finds the k most frequent gene identifiers.\n", - "\"\"\"\n", - "def get_most_frequent_gene_identifiers(identifier_occurrences, k):\n", - " most_frequent_identifiers = nlargest(k, identifier_occurrences.keys(), key=lambda identifier: identifier_occurrences[identifier])\n", - " \n", - " frequencies = []\n", - " for identifier in most_frequent_identifiers:\n", - " frequencies += [identifier_occurrences[identifier]]\n", - "\n", - " return most_frequent_identifiers, frequencies\n", - "\n", - "\"\"\"\n", - "Create a bar plot for the k most frequent gene identifiers.\n", - "\"\"\"\n", - "def plot_most_frequent_identifiers(input, output, k):\n", - " identifiers, frequencies = get_most_frequent_gene_identifiers(get_identifier_frequencies(input), k)\n", - "\n", - " fig, ax = plt.subplots(constrained_layout=True, dpi=200)\n", - " ax.bar(range(len(identifiers)), frequencies, tick_label=identifiers)\n", - " ax.set_xlabel(\"Gene identifier\")\n", - " ax.set_ylabel(\"Number of occurrences\")\n", - " ax.set_title(f\"{k} most frequent gene identifiers\")\n", - "\n", - " fig.savefig(output)\n", - "\n", - "get_most_frequent_gene_identifiers(get_identifier_frequencies(input), 5)\n", - "plot_most_frequent_identifiers(input, \"/content/drive/MyDrive/PythonProgramming/AtCol0_most_frequent_identifiers_bar_plot.png\", 5)" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 840 - }, - "id": "WcF-Tthazr3h", - "outputId": "f726e328-c477-4275-f32a-9d83f5d01f10" - }, - "execution_count": 6, - "outputs": [ - { - "output_type": "display_data", - "data": { - "text/plain": [ - "<Figure size 1200x800 with 1 Axes>" - ], - "image/png": "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x4nmN0G/Lc1PZVmKzvE3lrROVSJJ6wGzK97+M3BXnp/qzxUm1gpu0EblezYzMxsbrhwzMzOz6eTTwAN5/hhJGw8gz+/nv1tKevEA8uvXpcBNef4tklaZonL8JP8VsH9Nujk5zTLyY34/zIsvkrTVwErXn+KYQdJjprIgjM73bGZmNjZcOWZmZmbTRkT8BXhHXlwT+IWknerWkSRgrZokn6U1KuDXJT2lS34vk/S0hkVuLHcq//G8uAlwcl1FjqQ1JL190OUAzgJuzvOHS9qiw7a3Bj7UJZ9jgEdIv0fPkDSrKqGkGZJeV5dmgm4uzW86pG00MkLfs5mZ2dhwn2NmZmY2rUTElyVtBBwBPB64QNLPgLNJjwT+g9Tp+QbAs4D9gKLC6xHaOtOPiFskvRE4A9gQuFjSXOBHpBY+KwGzgG2BfUgVGi8HLh/C7n0R2A14JbAv8CxJJwG/IT2muAawJbArsCepRdQJgyxARDwk6RDS57E28GtJnwDmk1qK7Qq8Lye/DtisIp8rJL0HOB7YGrhS0peAn5FGuVyF9Fjm9qTPdUPgqbRaVQ3Sr0rzx0s6mlRhVjxuuSAiFg9hu1Wm/Hs2MzMbJ64cMzMzs2knIo6UdBlwHKmy6gV5qlwF+DFwWET8rUN+Z0raC5gLzAQOzFMnSxjSqIoREZL+hdSa7UBSK6dja1YZykiVETFP0mF522uRWoGVLSJVOh5GReVYzuczku4DPkNq6XdYnjp5iNLjj4MUEddJOp1U5hflqWxjmo8aOYjyjMT3bGZmNi78WKWZmZlNSxHxXWALUoXHV4GrgNuBxcDdwPWk/sQ+AGwaES+pGxkwIs4mVZK8h1brpoeB+3Ne5wCHArMj4n+GtFtExMMR8Tbg6cDnSa3h7iK1ersL+B1pf/cBhtaXV0QcB+wEnEmqnHkQuAH4GvCciPhBw3y+TKrAPAL4Ja3v6D7gWmAeqYJoo4i4bsC7UfZ64L20WmctGeK2uhqV79nMzGwcKA3sZGZmZmZmZmZmNn7ccszMzMzMzMzMzMaWK8fMzMzMzMzMzGxsuXLMzMzMzMzMzMzGlivHzMzMzMzMzMxsbLlyzMzMzMzMzMzMxpYrx8zMzMzMzMzMbGy5cszMzMzMzMzMzMaWK8fMzMzMzMzMzGxsuXLMzMzMzMzMzMzGlivHzMzMzMzMzMxsbLlyzMzMzMzMzMzMxpYrx8zMzMzMzMzMbGy5cszMzMzMzMzMzMaWK8fMzMzMzMzMzGxsuXLMzMzMzMzMzMzGlivHzMzMzMzMzMxsbLlyzMzMzMzMzMzMxpYrx8zMzMzMzMzMbGy5cszMzMzMzMzMzMaWK8fMzMzMzMzMzGxsuXLMzMzMzMzMzMzGlivHzMzMzMzMzMxsbLlyzMzMzMzMzMzMxpYrx8zMzMzMzMzMbGy5cszMzMzMzMzMzMbW/wGgY5b3OMms3wAAAABJRU5ErkJggg==\n" - }, - "metadata": { - "needs_background": "light" - } - } - ] - }, - { - "cell_type": "code", - "source": [ - "" - ], - "metadata": { - "id": "ELl7z1kg4xF7" - }, - "execution_count": null, - "outputs": [] - } - ] -} \ No newline at end of file diff --git a/Exercises/solutions/Python_course_2021_exercises_F.ipynb b/Exercises/solutions/Python_course_2021_exercises_F.ipynb deleted file mode 100644 index c58df78afd40b52f4b498425f1c6ab4a6dfd8db4..0000000000000000000000000000000000000000 --- a/Exercises/solutions/Python_course_2021_exercises_F.ipynb +++ /dev/null @@ -1,417 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "Python_course_2021_exercises_F.ipynb", - "provenance": [], - "collapsed_sections": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - } - }, - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "C6hjQZrrO1lx", - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "# Python course 2021 - Exercises F" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "RoMsf4tCO3CA", - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "## Part1 - DNA, RNA and peptide sequences" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "3_wMYLkSPBrx", - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "\n", - "\n", - "---\n", - "1.1) Write a function to get the reverse complement (upper case letters) of a DNA sequence given in upper case letters!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "Uq70MpOBPMpe", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "012a7aed-2e4e-4ac4-d32c-2b1b4e8c3784", - "pycharm": { - "name": "#%%\n" - } - }, - "source": [ - "def get_reverse_complement(sequence):\n", - " bases = {'A': 'T', 'T': 'A', 'C': 'G', 'G': 'C'}\n", - "\n", - " rev_comp = []\n", - " for i in range(len(sequence)-1, -1, -1):\n", - " rev_comp += [bases[sequence[i]]]\n", - "\n", - " return ''.join(rev_comp)\n", - "\n", - "sequence_1 = \"AGACGTA\"\n", - "print(sequence_1)\n", - "print(get_reverse_complement(sequence_1))\n", - "\n", - "sequence_2 = \"TTTGACGTAT\"\n", - "print(sequence_2)\n", - "print(get_reverse_complement(sequence_2))" - ], - "execution_count": 1, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "AGACGTA\n", - "TACGTCT\n", - "TTTGACGTAT\n", - "ATACGTCAAA\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "trElcFlcPMzg", - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "\n", - "\n", - "---\n", - "1.2) Write a function to convert a DNA sequence into a RNA sequence!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "ahMEGCWTPUAY", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "4f6e4e43-6b56-460b-fac9-4407444fd236", - "pycharm": { - "name": "#%%\n" - } - }, - "source": [ - "def convert_DNA_to_RNA(sequence):\n", - " rna_sequence = []\n", - " for character in sequence:\n", - " if character == \"T\":\n", - " rna_sequence += [\"U\"]\n", - " else:\n", - " rna_sequence += [character]\n", - "\n", - " return ''.join(rna_sequence)\n", - "\n", - "print(sequence_1)\n", - "print(convert_DNA_to_RNA(sequence_1))\n", - "\n", - "print(sequence_2)\n", - "print(convert_DNA_to_RNA(sequence_2))" - ], - "execution_count": 2, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "AGACGTA\n", - "AGACGUA\n", - "TTTGACGTAT\n", - "UUUGACGUAU\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "EOMgpzlnPUJ6", - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "\n", - "\n", - "---\n", - "1.3) Write a function to translate a DNA sequence into amino acids (first frame only)!\n", - "* Tip: [wiki - codon tables](https://en.wikipedia.org/wiki/DNA_and_RNA_codon_tables)\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "aFVhE4KEPrM4", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "d64ea5ed-0a79-4d75-95ae-4841ce40a6a3", - "pycharm": { - "name": "#%%\n" - } - }, - "source": [ - "codons = {\n", - " \"TTT\": \"F\", \"TTC\": \"F\",\n", - " \"TTA\": \"L\", \"TTG\": \"L\", \"CTT\": \"L\", \"CTC\": \"L\", \"CTA\": \"L\", \"CTG\": \"L\",\n", - " \"ATT\": \"I\", \"ATC\": \"I\", \"ATA\": \"I\",\n", - " \"ATG\": \"M\",\n", - " \"GTT\": \"V\", \"GTC\": \"V\", \"GTA\": \"V\", \"GTG\": \"V\",\n", - " \"TCT\": \"S\", \"TCC\": \"S\", \"TCA\": \"S\", \"TCG\": \"S\",\n", - " \"CCT\": \"P\", \"CCC\": \"P\", \"CCA\": \"P\", \"CCG\": \"P\",\n", - " \"ACT\": \"T\", \"ACC\": \"T\", \"ACA\": \"T\", \"ACG\": \"T\",\n", - " \"GCT\": \"A\",\"GCC\": \"A\", \"GCA\": \"A\", \"GCG\": \"A\",\n", - " \"TAT\": \"Y\", \"TAC\": \"Y\",\n", - " \"CAT\": \"H\", \"CAC\": \"H\",\n", - " \"CAA\": \"Q\", \"CAG\": \"Q\",\n", - " \"AAT\": \"N\", \"AAC\": \"N\",\n", - " \"AAA\": \"K\", \"AAG\": \"K\",\n", - " \"GAT\": \"D\", \"GAC\": \"D\",\n", - " \"GAA\": \"E\",\"GAG\": \"E\",\n", - " \"TGT\": \"C\", \"TGC\": \"C\",\n", - " \"TGG\": \"W\",\n", - " \"CGT\": \"R\", \"CGC\": \"R\", \"CGA\": \"R\", \"CGG\": \"R\",\n", - " \"AGT\": \"S\", \"AGC\": \"S\",\n", - " \"AGA\": \"R\", \"AGG\": \"R\",\n", - " \"GGT\": \"G\", \"GGC\": \"G\", \"GGA\": \"G\", \"GGG\": \"G\",\n", - " \"TGA\": \"*\", \"TAA\": \"*\", \"TAG\": \"*\",\n", - "}\n", - "\n", - "def translate(sequence):\n", - " peptide_sequence = []\n", - " for i in range(0, len(sequence) - 2, 3):\n", - " peptide_sequence += [codons[sequence[i: i+3]]]\n", - " return ''.join(peptide_sequence)\n", - "\n", - "sequence = \"ATGCATGGTTGAGGCGGCATGCGTCGCGATTGG\"\n", - "print(translate(sequence))" - ], - "execution_count": 3, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "MHG*GGMRRDW\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "3-KHtLeePsQ4", - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "\n", - "\n", - "---\n", - "1.4) Write a function to translate DNA sequences in all 6 frames into peptide sequences! The longest peptide sequence per DNA sequence should be returned!\n" - ] - }, - { - "cell_type": "code", - "metadata": { - "id": "s50AlgALP8I3", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "436613c5-0516-4f89-dc88-00427ecab66c", - "pycharm": { - "name": "#%%\n" - } - }, - "source": [ - "\"\"\"\n", - "Translates a DNA sequence in all 6 frames into peptide sequences\n", - "and yields the peptide sequences.\n", - "\"\"\"\n", - "def translate_all_frames(sequence):\n", - " for i in range(3):\n", - " yield translate(sequence[i:])\n", - " \n", - " rev_comp = get_reverse_complement(sequence)\n", - " for i in range(3):\n", - " yield translate(rev_comp[i:])\n", - "\n", - "\"\"\"\n", - "Find a longest valid peptide sequence, meaning one that starts with\n", - "M, in a peptide sequence.\n", - "\"\"\"\n", - "def get_longest_peptide_sequence(sequence):\n", - " longest_length = 0\n", - " longest_peptide_sequence = \"\"\n", - " \n", - " current_sequence = []\n", - " currently_in_sequence = False\n", - " for peptide in sequence:\n", - " if currently_in_sequence:\n", - " # encounter a stop codon\n", - " if peptide == \"*\":\n", - " if current_sequence:\n", - " # update longest observed sequence and length if necessary\n", - " if len(current_sequence) > longest_length:\n", - " longest_length = len(current_sequence)\n", - " longest_peptide_sequence = ''.join(current_sequence)\n", - " # clear current sequence\n", - " current_sequence = []\n", - " currently_in_sequence = False\n", - " else:\n", - " # sequence extend continues\n", - " current_sequence += [peptide]\n", - " # currently not in a valid peptide sequence\n", - " else:\n", - " # encounter a start peptide\n", - " if peptide == \"M\":\n", - " current_sequence += [peptide]\n", - " currently_in_sequence = True\n", - " # if we are not in a valid peptide sequence and the current peptide is not\n", - " # a start peptide, simply continue\n", - "\n", - " if current_sequence:\n", - " if len(current_sequence) > longest_length:\n", - " longest_length = len(current_sequence)\n", - " longest_peptide_sequence = ''.join(current_sequence)\n", - "\n", - " return longest_peptide_sequence\n", - "\n", - "\"\"\"\n", - "Computes a longest valid peptide sequence for each of the 6 frames and yields it.\n", - "\"\"\"\n", - "def longest_peptide_sequence_per_frame(sequence):\n", - " for frame in translate_all_frames(sequence):\n", - " yield get_longest_peptide_sequence(frame)\n", - "\n", - "print(\"Reading frames:\")\n", - "for frame in translate_all_frames(sequence):\n", - " print(frame)\n", - "print(\"\")\n", - "\n", - "print(\"Longest valid peptide sequence:\")\n", - "print(get_longest_peptide_sequence(translate(sequence)))\n", - "print(\"\")\n", - "\n", - "print(\"Longest valid peptide sequence per frame:\")\n", - "for longest_peptide_sequence in longest_peptide_sequence_per_frame(sequence):\n", - " print(longest_peptide_sequence)" - ], - "execution_count": 4, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Reading frames:\n", - "MHG*GGMRRDW\n", - "CMVEAACVAI\n", - "AWLRRHASRL\n", - "PIATHAASTMH\n", - "QSRRMPPQPC\n", - "NRDACRLNHA\n", - "\n", - "Longest valid peptide sequence:\n", - "MRRDW\n", - "\n", - "Longest valid peptide sequence per frame:\n", - "MRRDW\n", - "MVEAACVAI\n", - "\n", - "MH\n", - "MPPQPC\n", - "\n" - ] - } - ] - }, - { - "cell_type": "markdown", - "source": [ - "---\n", - "Human Dataset\n", - "\n", - "1.1) Count number of unique genes from the file \"genes_human_genenames_duplicates.txt\" and write the gene names in a new file." - ], - "metadata": { - "id": "ey-lNS6d9XIQ", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "source": [ - "from google.colab import drive\n", - "drive.mount('/content/drive')\n", - "\n", - "with open(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/genes_human_genenames_duplicates.txt\", 'r') as genes:\n", - " with open(\"/content/drive/MyDrive/ColabNotebooks/UniPythonCourse/Exercises/data/gene_names_unique_human.txt\", 'w') as new_file:\n", - " unique_genes = []\n", - " line = genes.readline()\n", - " while line:\n", - " if '.' in line:\n", - " line = line[:line.find('.')] # dismiss the transcript number\n", - " if not line in unique_genes: # Check if the gene was already encountered and write it in the new file if not\n", - " unique_genes.append(line)\n", - " new_file.write(line)\n", - " line = genes.readline()\n", - " " - ], - "metadata": { - "id": "K_sqSkLx90lo", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "49045a1e-a48e-494e-ba71-82de736c9e84", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 6, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Mounted at /content/drive\n" - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/Exercises/solutions/gap_exercise1_basics.ipynb b/Exercises/solutions/gap_exercise1_basics.ipynb deleted file mode 100644 index 5c21523c775b17b837f468bf387e53f0a5d1fe46..0000000000000000000000000000000000000000 --- a/Exercises/solutions/gap_exercise1_basics.ipynb +++ /dev/null @@ -1,463 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "gaps_exercises1.ipynb", - "provenance": [], - "collapsed_sections": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, - "cells": [ - { - "cell_type": "markdown", - "source": [ - "# Python course - Exercises Gap text" - ], - "metadata": { - "id": "kH0p2uT-sQ6y", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "markdown", - "source": [ - "Correct the Code" - ], - "metadata": { - "id": "uW9SoYEyrlRL", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "source": [ - "# What is missing here? Expected output: Hi!\n", - "print('Hi!')" - ], - "metadata": { - "id": "Qflb9AWfrykh", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 5, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hi!\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Here are two mistakes. Can you find them?\n", - "# Hi! I am a comment. How are you?\n", - "print('Hello world!')" - ], - "metadata": { - "id": "eemU0jTksxu5", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 6, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello world!\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Multi-line comments\n", - "\"\"\"\n", - "I want to be a\n", - "mutli line comment.\n", - "\"\"\" \n", - "print('Hello world!')" - ], - "metadata": { - "id": "2ysNg9wDtaZ9", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 7, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello world!\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Expected output: 5\n", - "c = 5\n", - "print(c)" - ], - "metadata": { - "id": "Vexbuvx1u1NS", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 8, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# How to print two strings as one. Expected output: Hello world\n", - "a = 'Hello '\n", - "b = 'world'\n", - "print( a + b )" - ], - "metadata": { - "id": "cGTJ95-9wzLT", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 9, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello world\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Variable types\n", - "# Does the error output help you?\n", - "a = 'Hello'\n", - "b = 0\n", - "print( a + str(b) )" - ], - "metadata": { - "id": "6QiU3l2_xFnP", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 10, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello0\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# What is missing?\n", - "a = 'Hello'\n", - "b = a\n", - "\n", - "if a == b:\n", - " print('Same!')" - ], - "metadata": { - "id": "_YtGF9xqzFoR", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 11, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Same!\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Print the variable type\n", - "# Expected output: a is of type <class 'str'>\n", - "a = 'How are you?'\n", - "print('a is of type', type(a))" - ], - "metadata": { - "id": "wH0ifA4czyDV", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 12, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "a is of type <class 'str'>\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Variable names: What is allowed and what not?\n", - "_1th_string = \"Hello\"\n", - "second_string = 'world'\n", - "third_string = '!'\n", - "FOURTH_STRING = 'How'\n", - "FIFTH_STRING = 'are'\n", - "_6th_string = 'you?'\n", - "\n", - "print(_1th_string, second_string, \n", - " third_string, FOURTH_STRING,\n", - " FIFTH_STRING, _6th_string\n", - " )" - ], - "metadata": { - "id": "Spcu5lGc0Uv9", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 13, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello world ! How are you?\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# convert b into float\n", - "a = 2\n", - "b = float(a)\n", - "print(b)" - ], - "metadata": { - "id": "_TcdURMh2yJZ", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 14, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2.0\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# How to access Lists?\n", - "my_list = [\"!\", \"Hello\", 'you', \"How\", '?', 1, 'are', 2, 3, \"world\"]\n", - "print(my_list)\n", - "print(my_list[ 0 ]) # print '!'\n", - "print(my_list[ 1 ]) # print 'Hello'\n", - "print(my_list[ -1 ]) # print the last element of a list without the real index; here 'world'\n", - "### print 'Hello world! How are you?':\n", - "print(my_list[ 1 ], my_list[ -1 ] ,my_list[0] ,my_list[ 3 ] ,my_list[ -4 ] ,my_list[ 2 ], my_list[4])" - ], - "metadata": { - "id": "5VripGXYxBf8", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 15, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['!', 'Hello', 'you', 'How', '?', 1, 'are', 2, 3, 'world']\n", - "!\n", - "Hello\n", - "world\n", - "Hello world ! How are you ?\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Indices of Strings\n", - "a = 'Hello world!'\n", - "print(a[ -1 ]) # only print !\n", - "print(a[ 0 ]) # only print H\n", - "print(a[ 6:-1 ]) # only print 'world', without '!'" - ], - "metadata": { - "id": "V3VJP2gg1HLT", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 16, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "!\n", - "H\n", - "world\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Dictionaries\n", - "my_dict = { 'chr1' : 'gene1', 'chr2' : 'gene3' }\n", - "print(my_dict[ 'chr1' ]) # print gene1 of the dictionary" - ], - "metadata": { - "id": "6e6KYBcQ0qa3", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 17, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "gene1\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Dictionaries2; Find the mistake\n", - "my_dict = { 'chr1' : 'gene1', 'chr2' : 'gene3' }\n", - "print(my_dict[ 'chr1' ]) # print gene1 of the dictionary" - ], - "metadata": { - "id": "44dxJxK2bR2n", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 18, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "gene1\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Dictionaries3\n", - "my_dict = { 'chr1' : ['gene1', 'gene2'], 'chr2' : 'gene3' }\n", - "print(my_dict[ 'chr1' ][ 1 ]) # print gene2 of the dictionary" - ], - "metadata": { - "id": "RdIWfnVsbpVF", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 19, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "gene2\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# Booleans\n", - "a = 0\n", - "b = 1\n", - "print(bool( b )) # print True; insert the right variable\n", - "print(bool( a )) # print False; insert the right variable" - ], - "metadata": { - "id": "PrmB8FZD0-PQ", - "pycharm": { - "name": "#%%\n" - } - }, - "execution_count": 20, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n", - "False\n" - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/Exercises/solutions/gap_exercise2_functions.ipynb b/Exercises/solutions/gap_exercise2_functions.ipynb deleted file mode 100644 index d8c28af35b1d9ec8c29a9335190e8e5297cee99e..0000000000000000000000000000000000000000 --- a/Exercises/solutions/gap_exercise2_functions.ipynb +++ /dev/null @@ -1,166 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "gap_exercise2_functions.ipynb", - "provenance": [], - "collapsed_sections": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, - "cells": [ - { - "cell_type": "markdown", - "source": [ - "# Python course - Exercises Gap text" - ], - "metadata": { - "id": "kH0p2uT-sQ6y", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "markdown", - "source": [ - "Correct the Code" - ], - "metadata": { - "id": "uW9SoYEyrlRL", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "source": [ - "# How are functions defined?\n", - "def my_function(b):\n", - " print(b+10)\n", - "\n", - "a=5\n", - "my_function(a)" - ], - "metadata": { - "id": "uoscfCSCK980", - "pycharm": { - "name": "#%%\n" - }, - "outputId": "8fcbf234-1326-4646-dd6e-22fd75234693", - "colab": { - "base_uri": "https://localhost:8080/" - } - }, - "execution_count": 1, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "15\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# What is missing?\n", - "def concat_sequences( seq1, seq2, seq3 ):\n", - " print(seq1 + seq2 + seq3)\n", - "\n", - "concat_sequences('ACGTC', 'GTCAA', 'TTACC')" - ], - "metadata": { - "id": "VI2uTjtJMZ-L", - "pycharm": { - "name": "#%%\n" - }, - "outputId": "0325b131-f435-4260-df26-4d917944680d", - "colab": { - "base_uri": "https://localhost:8080/" - } - }, - "execution_count": 3, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "ACGTCGTCAATTACC\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# correct the code such that the function delivers b+10\n", - "def my_function(b):\n", - " return (b+10)\n", - "\n", - "result = my_function(5)\n", - "print(result)" - ], - "metadata": { - "id": "GN89HlxMJRAQ", - "pycharm": { - "name": "#%%\n" - }, - "outputId": "01ad604f-0877-457e-fabc-2cb8b922fc2a", - "colab": { - "base_uri": "https://localhost:8080/" - } - }, - "execution_count": 4, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "15\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# undefined number of arguments: what is needed?\n", - "def concat_sequences( seq ):\n", - " print(seq[0] + seq[1] + seq[2])\n", - "\n", - "concat_sequences(['ACGTC', 'GTCAA', 'TAGCTGC'])" - ], - "metadata": { - "id": "UOsFUQSHKGXH", - "pycharm": { - "name": "#%%\n" - }, - "outputId": "1fd92f39-73a6-4777-cddb-b7cf6c9108ad", - "colab": { - "base_uri": "https://localhost:8080/" - } - }, - "execution_count": 7, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "ACGTCGTCAATAGCTGC\n" - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/Exercises/solutions/gap_exercise3_if_else.ipynb b/Exercises/solutions/gap_exercise3_if_else.ipynb deleted file mode 100644 index 6bf7f47582825e9ad0018392fe5b8b0b8de0dbcf..0000000000000000000000000000000000000000 --- a/Exercises/solutions/gap_exercise3_if_else.ipynb +++ /dev/null @@ -1,211 +0,0 @@ -{ - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "name": "gap_exercise3_if_else.ipynb", - "provenance": [], - "collapsed_sections": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, - "cells": [ - { - "cell_type": "markdown", - "source": [ - "# Python course - Exercises Gap text" - ], - "metadata": { - "id": "kH0p2uT-sQ6y", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "markdown", - "source": [ - "Correct the Code" - ], - "metadata": { - "id": "uW9SoYEyrlRL", - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "source": [ - "# complete the statement for b larger than a\n", - "a = 5\n", - "b = 10\n", - "\n", - "if b > a:\n", - " print('b larger a')" - ], - "metadata": { - "id": "uoscfCSCK980", - "pycharm": { - "name": "#%%\n" - }, - "outputId": "9b383eb8-a957-4975-9ece-bdebb1bbf55e", - "colab": { - "base_uri": "https://localhost:8080/" - } - }, - "execution_count": 1, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "b larger a\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# complete the statements\n", - "a = 5\n", - "b = 10\n", - "c = 5\n", - "\n", - "if(a < b) and (a == c):\n", - " print('a smaller b, but a equals c')" - ], - "metadata": { - "id": "9DGKzqxWdABE", - "pycharm": { - "name": "#%%\n" - }, - "outputId": "eeb99a8a-426d-4a9f-fc6a-bf035e67b31d", - "colab": { - "base_uri": "https://localhost:8080/" - } - }, - "execution_count": 2, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "a smaller b, but a equals c\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# complete the statements\n", - "a = 5\n", - "b = 10\n", - "c = 5\n", - "\n", - "if a <= c:\n", - " print('a smaller or equal c')\n", - "elif a >= b:\n", - " print('a larger or equal b')" - ], - "metadata": { - "id": "3ipcaNRCdv9S", - "pycharm": { - "name": "#%%\n" - }, - "outputId": "96acdcd0-91e1-443b-b6de-7f6a95239a91", - "colab": { - "base_uri": "https://localhost:8080/" - } - }, - "execution_count": 3, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "a smaller or equal c\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# complete the statements\n", - "a = 5\n", - "b = 10\n", - "c = 5\n", - "\n", - "if a != c:\n", - " print('a not c')\n", - "elif a == b:\n", - " print('a equals b')\n", - "else:\n", - " print('None of the above is true')" - ], - "metadata": { - "id": "w9QBlM8Hel_u", - "pycharm": { - "name": "#%%\n" - }, - "outputId": "5c9c3e63-7ec3-417d-c08d-f9f8ee6f9b92", - "colab": { - "base_uri": "https://localhost:8080/" - } - }, - "execution_count": 4, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "None of the above is true\n" - ] - } - ] - }, - { - "cell_type": "code", - "source": [ - "# complete the statements\n", - "a = 5\n", - "b = 10\n", - "c = 5\n", - "\n", - "if (a != c) or (b != c):\n", - " print('a not c OR b not c')\n", - "else:\n", - " print('None of the above is true')" - ], - "metadata": { - "id": "5KfDsRHLfW7k", - "pycharm": { - "name": "#%%\n" - }, - "outputId": "7d073833-18cf-4de7-9814-f3d422642b4b", - "colab": { - "base_uri": "https://localhost:8080/" - } - }, - "execution_count": 5, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "a not c OR b not c\n" - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index c8232cd0429af755818841af6fef13178d9421d1..0000000000000000000000000000000000000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Applied Python Programming for Life Scientists - -This course is intended for life scientists without any prior knowledge about bioinformatics/programming. The objective is to provide a sufficient amount of knowledge about Python to solve small problems by writing simple scripts. diff --git a/Slides_set1.pdf b/Slides_set1.pdf deleted file mode 100644 index ed3b4c248d8dd825e29b260b41983432b7a7c119..0000000000000000000000000000000000000000 Binary files a/Slides_set1.pdf and /dev/null differ diff --git a/Slides_set2.pdf b/Slides_set2.pdf deleted file mode 100644 index 07ee1122f89e764e557a25fc3aa181a4c6216b33..0000000000000000000000000000000000000000 Binary files a/Slides_set2.pdf and /dev/null differ diff --git a/Slides_set3.pdf b/Slides_set3.pdf deleted file mode 100644 index 3daefd2688089887698aa1d74739945235500e00..0000000000000000000000000000000000000000 Binary files a/Slides_set3.pdf and /dev/null differ diff --git a/Slides_set4.pdf b/Slides_set4.pdf deleted file mode 100644 index 66bee4f95396a96ff08839f16b2d159ff833e5d0..0000000000000000000000000000000000000000 Binary files a/Slides_set4.pdf and /dev/null differ diff --git a/Slides_set5.pdf b/Slides_set5.pdf deleted file mode 100644 index af789bba1148e09581624eb2889cf3519c0af272..0000000000000000000000000000000000000000 Binary files a/Slides_set5.pdf and /dev/null differ diff --git a/Slides_set6.pdf b/Slides_set6.pdf deleted file mode 100644 index b5393c032cc809af68e7afbdaf78a10d1afa628b..0000000000000000000000000000000000000000 Binary files a/Slides_set6.pdf and /dev/null differ diff --git a/Slides_set7.pdf b/Slides_set7.pdf deleted file mode 100644 index a88dce80368a66087aa248270a6e029543f87f20..0000000000000000000000000000000000000000 Binary files a/Slides_set7.pdf and /dev/null differ diff --git a/Slides_set8.pdf b/Slides_set8.pdf deleted file mode 100644 index 0c60dbd6069b6db47eb1ffa93365c5e2db6a76f6..0000000000000000000000000000000000000000 Binary files a/Slides_set8.pdf and /dev/null differ diff --git a/Slides_set9.pdf b/Slides_set9.pdf deleted file mode 100644 index 8954e12d3093d6dbf9f680ad7722cca01e5bacf8..0000000000000000000000000000000000000000 Binary files a/Slides_set9.pdf and /dev/null differ diff --git a/Syllabus_Python_Programming_for_Life_Scientists_WS2021_2022.pdf b/Syllabus_Python_Programming_for_Life_Scientists_WS2021_2022.pdf deleted file mode 100644 index f2a60b7946f0fb2c2f0f3b003a6140da2a3033c0..0000000000000000000000000000000000000000 Binary files a/Syllabus_Python_Programming_for_Life_Scientists_WS2021_2022.pdf and /dev/null differ diff --git a/Vorbesprechung_2022.pdf b/Vorbesprechung_2022.pdf deleted file mode 100644 index b4008ea1d813e83eadf37c1a0ad30b5bc5a7dfd9..0000000000000000000000000000000000000000 Binary files a/Vorbesprechung_2022.pdf and /dev/null differ