<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://teaching.healthtech.dtu.dk/22126/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Gabre</id>
	<title>22126 - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://teaching.healthtech.dtu.dk/22126/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Gabre"/>
	<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php/Special:Contributions/Gabre"/>
	<updated>2026-05-05T19:44:56Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=195</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=195"/>
		<updated>2025-01-23T09:05:21Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2025/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2025/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2025/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2025/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2025/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2025/42_post_alignment_variantcalling_part1_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2025/43_post_alignment_variantcalling_part2_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2025/51_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2025/Long_read_sequencing_Lecture_09-01-2025.pptx Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2025/dtu_adna_2025_red.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]]) &amp;lt;!-- ([[Rnaseq_exercise_answers]]) --&amp;gt; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2025/Genomic_epidemiology_NGScourse_Jan2025.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2025/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2023/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;recap test &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2025])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancer-seq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce poster&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=194</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=194"/>
		<updated>2025-01-20T08:11:15Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2025/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2025/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2025/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2025/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2025/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2025/42_post_alignment_variantcalling_part1_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2025/43_post_alignment_variantcalling_part2_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2025/51_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2025/Long_read_sequencing_Lecture_09-01-2025.pptx Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2025/dtu_adna_2025_red.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]]) &amp;lt;!-- ([[Rnaseq_exercise_answers]]) --&amp;gt; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2025/Genomic_epidemiology_NGScourse_Jan2025.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2025/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2023/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;recap test &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2025])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancer-seq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=QuantitativeMetagenomics&amp;diff=193</id>
		<title>QuantitativeMetagenomics</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=QuantitativeMetagenomics&amp;diff=193"/>
		<updated>2025-01-14T13:11:41Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&amp;lt;H3&amp;gt;Overview&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Since metagenomics data is often very large, it requires a lot of computational resources and time, we have cheated a little bit and prepared some data for you in advance!&lt;br /&gt;
&lt;br /&gt;
In this exercise, we have done the assembly and counting across a cohort of hundreds of human fecal&lt;br /&gt;
samples in advance and in addition provide the gene-wise taxonomy and the BMI of the&lt;br /&gt;
human donors.&lt;br /&gt;
From this data, we shall estimate the species richness,and  diversity and look at the effect of&lt;br /&gt;
downsizing. Furthermore, we shall see if we can identify any differences between the&lt;br /&gt;
microbiome of lean and obese.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Becoming a pirate&amp;lt;/H3&amp;gt;&lt;br /&gt;
This exercise uses R either locally (install RStudio on your own machine) or on the server by typing &lt;br /&gt;
&amp;lt;pre&amp;gt;R&amp;lt;/pre&amp;gt;&lt;br /&gt;
First, IF you are running RStudio locally you will need to install a package called &amp;quot;vegan&amp;quot;&lt;br /&gt;
&amp;lt;pre&amp;gt;install.packages(&amp;quot;vegan&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, let’s load the &amp;quot;vegan&amp;quot; package and thereafter load the read count data from a series of stool samples.&lt;br /&gt;
&amp;lt;pre&amp;gt;library(&amp;quot;vegan&amp;quot;)&lt;br /&gt;
load(url(&amp;quot;https://teaching.healthtech.dtu.dk/material/22126/Counts_NGS.RData&amp;quot;))&lt;br /&gt;
head(Counts)&lt;br /&gt;
str(Counts)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Q1. How many samples do we have and how many genes?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The different samples may have been sequenced to different depths. Try to count the reads per sample&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sampleDepth&amp;lt;-(colSums(Counts))&lt;br /&gt;
hist(sampleDepth, breaks=100, ylab=&amp;quot;Number of samples&amp;quot;, xlab=&amp;quot;Number of reads&amp;quot;, main=&amp;quot;Sample depth&amp;quot;)&lt;br /&gt;
range(sampleDepth)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q2. Whats the sample depth range?&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;H3&amp;gt;Species&amp;lt;/H3&amp;gt;&lt;br /&gt;
Lets get the genes associated to species. Here is the gene-wise species taxonomy&lt;br /&gt;
&amp;lt;pre&amp;gt;load(url(&amp;quot;https://teaching.healthtech.dtu.dk/material/22126//taxonomy_species.RData&amp;quot;))&lt;br /&gt;
head(taxonomy_species)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We then combine (by summing) the read counts pr. gene to read counts per species.&lt;br /&gt;
&amp;lt;pre&amp;gt;taxCounts&amp;lt;-apply(Counts, 2, tapply, INDEX=taxonomy_species, sum)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try looking at the taxCounts matrix&lt;br /&gt;
&amp;lt;pre&amp;gt;str(taxCounts)&lt;br /&gt;
head(taxCounts)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Q3. How many species are there in total?&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;H3&amp;gt;Richness and Diversity&amp;lt;/H3&amp;gt;&lt;br /&gt;
What is the species richness and diversity (Shannon) for the different samples.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q4. What does a high Shannon diversity index mean?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
OK, lets see it for our samples&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
species_richness&amp;lt;-(colSums(taxCounts&amp;gt;0))&lt;br /&gt;
names(species_richness)&amp;lt;-NULL&lt;br /&gt;
require(vegan)&lt;br /&gt;
speciesDiversity&amp;lt;-diversity(t(taxCounts), index = &amp;quot;shannon&amp;quot;)&lt;br /&gt;
names(speciesDiversity)&amp;lt;-NULL &lt;br /&gt;
par(mfrow=c(1,1))&lt;br /&gt;
barplot(sort(species_richness), las=3, main=&amp;quot;Species richness&amp;quot;, xlab=&amp;quot;Samples&amp;quot;, ylab=&amp;quot;Richness&amp;quot;)&lt;br /&gt;
barplot(sort(speciesDiversity), xlab=&amp;quot;Samples&amp;quot;, las=3, main=&amp;quot;Diversity (Shannon)&amp;quot;)&lt;br /&gt;
plot(species_richness,speciesDiversity,xlab=&amp;quot;Richness&amp;quot;, ylab=&amp;quot;Shannon diversity index&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:raw_richness.png]][[File:raw_shannon.png]][[File:raw_richnessVSshannonZoom.png]]&lt;br /&gt;
&lt;br /&gt;
Each samples or persons richness and diversity is shown and the third plot shows each sample/persons richness &amp;amp; diversity as a dot.&lt;br /&gt;
&amp;lt;H3&amp;gt;Downsizing or rarefying&amp;lt;/H3&amp;gt;&lt;br /&gt;
But this was on the raw count data with different sampling depth (number of counts) per sample. We should downsize so that we get fair comparisons.&lt;br /&gt;
&lt;br /&gt;
First suggest the number of reads we should sample per sample for the downsizing [target]. If we chose a low target we will loose abundance resolution and detection sensitivity. If we chose it higher we will loose samples.&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;gt; plot(sampleDepth, pch=20, log=&amp;quot;y&amp;quot;, xlab=&amp;quot;Samples&amp;quot;, ylab=&amp;quot;Number of reads&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:raw_sampledepth.png]]&lt;br /&gt;
&lt;br /&gt;
There is no right answer (but there are less good suggestions). Insert the number you want to downsize to below and plot it again - the samples above the horizontal line we will keep and the samples below the line we will throw out.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; downsizeTarget &amp;lt;- INSERT NUMBER&lt;br /&gt;
&amp;gt; plot(sampleDepth, pch=20, log=&amp;quot;y&amp;quot;, xlab=&amp;quot;Samples&amp;quot;, ylab=&amp;quot;Number of reads&amp;quot;); abline(h=downsizeTarget)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:downsized_sampledepth.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q5. Which threshold did you chose and why? How many samples did you loose?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
OK lets downsize&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; dz_Counts&amp;lt;-round(t(t(Counts)*downsizeTarget/sampleDepth))&lt;br /&gt;
&amp;gt; weak_samples&amp;lt;-sampleDepth&amp;lt;downsizeTarget&lt;br /&gt;
&amp;gt; dz_Counts[,weak_samples]&amp;lt;-NA # samples that did not make the cut&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a quick and dirty downsizing (ideally one resampled the reads to a given depth, but that will take days)&lt;br /&gt;
Count the species again, now on the downsized data.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dz_taxCounts&amp;lt;-apply(dz_Counts, 2, tapply, INDEX=taxonomy_species, sum); gc() &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the richness and diversity again, now on downsized data&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; dz_species_richness&amp;lt;-(colSums(dz_taxCounts&amp;gt;0))&lt;br /&gt;
&amp;gt; names(dz_species_richness)&amp;lt;-NULL&lt;br /&gt;
&amp;gt; require(vegan)&lt;br /&gt;
&amp;gt; dz_speciesDiversity&amp;lt;-diversity(t(dz_taxCounts), index = &amp;quot;shannon&amp;quot;)&lt;br /&gt;
&amp;gt; dz_speciesDiversity[weak_samples]&amp;lt;-NA&lt;br /&gt;
&amp;gt; names(dz_speciesDiversity)&amp;lt;-NULL&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now plot the richness and diversity with downsized data&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; par(mfrow=c(1,1), pch=1)&lt;br /&gt;
&amp;gt; barplot(sort(dz_species_richness), las=3, main=&amp;quot;Species richness (Downsized)&amp;quot;, xlab=&amp;quot;Species&amp;quot;, ylab=&amp;quot;Richness&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:downsized_richness.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
barplot(sort(dz_speciesDiversity), las=3,main=&amp;quot;Shannon&#039;s diversity index (downsized)&amp;quot;, xlab=&amp;quot;Species&amp;quot;, ylab=&amp;quot;Shannon diversity&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:downsized_shannon.png]]&lt;br /&gt;
&lt;br /&gt;
And compare to the raw data&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; plot(dz_species_richness,species_richness, xlab=&amp;quot;downsized richness&amp;quot;, ylab=&amp;quot;raw richness&amp;quot;, main=&amp;quot;Richness&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:Comparing_richness.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; plot(dz_speciesDiversity,speciesDiversity,xlab=&amp;quot;downsized species diversity&amp;quot;, ylab=&amp;quot;raw species diversity&amp;quot;,main=&amp;quot;Diversity (Shannon)&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:Comparing_shannon.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q6. What is the effect on the downsizing on richness&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q7. What is the effect on the downsizing on diversity (shannon)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lets plot the abundance of each species in a sample with low diversity and a sample with high diversity. You should be able to see a clear difference between the two samples!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; par(mfrow=c(1,2))&lt;br /&gt;
&amp;gt; barplot(taxCounts[,4], main=&amp;quot;Person 4, SD &amp;gt; 3&amp;quot;, xaxt=&amp;quot;n&amp;quot;, xlab=&amp;quot;Species&amp;quot;, ylab=&amp;quot;Normalized abundance&amp;quot;)&lt;br /&gt;
&amp;gt; barplot(taxCounts[,240], main=&amp;quot;Person 240, SD &amp;lt; 0.5&amp;quot;, xaxt=&amp;quot;n&amp;quot;, xlab=&amp;quot;Species&amp;quot;, ylab=&amp;quot;Normalized abundance&amp;quot;)&lt;br /&gt;
&amp;gt; par(mfrow=c(1,1))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:comparing_species_abundance.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Comparisons&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now lets see if there is a difference between the microbiome of lean and obese humans. But first load some sample more information: BMI and Class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; load(url(&amp;quot;https://teaching.healthtech.dtu.dk/material/22126/BMI.RData&amp;quot;))&lt;br /&gt;
&amp;gt; boxplot(BMI$BMI.kg.m2 ~ BMI$Class, col=c(&amp;quot;red&amp;quot;, &amp;quot;gray&amp;quot;,&amp;quot;blue&amp;quot;), ylab=&amp;quot;BMI&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:bmi_class.png]]&lt;br /&gt;
&lt;br /&gt;
Class are: le = Lean; ow = Overweight; ob = Obese&lt;br /&gt;
&lt;br /&gt;
First let us see if the abundance of E. coli differs between obese and lean individuals using a Wilcoxon rank sum test (look for the p-value in the output), also lets get the mean abundance of E. coli in the tree groups :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; wilcox.test(x=dz_taxCounts[&amp;quot;Escherichia coli&amp;quot;,BMI$Classification==&amp;quot;ob&amp;quot;], y=dz_taxCounts[&amp;quot;Escherichia coli&amp;quot;,BMI$Classification==&amp;quot;le&amp;quot;] )&lt;br /&gt;
&amp;gt; tapply(dz_taxCounts[&amp;quot;Escherichia coli&amp;quot;,], BMI$Classification, mean, na.rm=TRUE)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q8. Is there any significant difference in abundance of E. coli between the different BMI groups?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s test all species correcting for multiple testing using Benjamini-Hochberg (False Discovery Rate) (we are testing 120 species) and plot them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; pval&amp;lt;-apply(dz_taxCounts, 1, function(V){wilcox.test(x=V[BMI$Classification==&amp;quot;ob&amp;quot;],y=V[BMI$Classification==&amp;quot;le&amp;quot;])$p.value})&lt;br /&gt;
&amp;gt; Abundance_ratio&amp;lt;-log2(apply(dz_taxCounts, 1,function(V){mean(x=V[BMI$Classification==&amp;quot;ob&amp;quot;], na.rm=TRUE)/mean(V[BMI$Classification==&amp;quot;le&amp;quot;], na.rm=TRUE)}))&lt;br /&gt;
&amp;gt; pval.adjust = p.adjust(pval, method=&amp;quot;BH&amp;quot;)&lt;br /&gt;
&amp;gt; plot(sort(pval.adjust), log=&amp;quot;y&amp;quot;, pch=16, xlab=&amp;quot;Species&amp;quot;, ylab=&amp;quot;p-values&amp;quot;)&lt;br /&gt;
&amp;gt; abline(h=0.05, col=&amp;quot;grey&amp;quot;, lty=2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q9. How many species are significant with an false discovery rate &amp;lt; 0.05?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Let us look at the top 10 most significant species abundance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; o&amp;lt;-order(pval)&lt;br /&gt;
&amp;gt; BMIstat&amp;lt;-data.frame(pval,pval.adjust, Abundance_ratio)[o,]&lt;br /&gt;
&amp;gt; BMIstat[1:10,]&lt;br /&gt;
&amp;gt; par(mar=c(5,18,5,5))&lt;br /&gt;
&amp;gt; barplot(BMIstat[1:10,3], names.arg=rownames(BMIstat)[1:10], las=1,xlab=&amp;quot;log fold difference between lean and obese&amp;quot;, horiz=TRUE)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:log_fold_diff_sign.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q10. Can you see any differences in the abundances - which species have large differences, what are their p-values?&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q11. What type of bacteria is the most significant one? [try google]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Beta-diversity and PCA&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Plot the Bray-curtis distance between samples as a heatmap.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
library(RColorBrewer)&lt;br /&gt;
library(gplots)&lt;br /&gt;
vdist = as.matrix(vegdist(t(taxCounts)))&lt;br /&gt;
rownames(vdist) = colnames(vdist)&lt;br /&gt;
hmcol = colorRampPalette(brewer.pal(9, &amp;quot;GnBu&amp;quot;))(100)&lt;br /&gt;
heatmap.2(vdist, trace=&#039;none&#039;, col=rev(hmcol))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q12. Can you see some clusters of samples?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Finally for the PCA:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; my.rda &amp;lt;- rda(t(taxCounts))&lt;br /&gt;
&amp;gt; biplot(my.rda, display = c(&amp;quot;sites&amp;quot;, &amp;quot;species&amp;quot;), type = c(&amp;quot;text&amp;quot;, &amp;quot;points&amp;quot;))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q13. Can you see which species that seems to be driving the differences between the samples?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Statistically modelling the variance using DESeq2&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, we will see the power of statistically modelling the variance instead of downsizing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; if (!requireNamespace(&amp;quot;BiocManager&amp;quot;, quietly = TRUE))&lt;br /&gt;
&amp;gt; install.packages(&amp;quot;BiocManager&amp;quot;)&lt;br /&gt;
&amp;gt; BiocManager::install(&amp;quot;DESeq2&amp;quot;)&lt;br /&gt;
&amp;gt; library(DESeq2)&lt;br /&gt;
&amp;gt; cts &amp;lt;- taxCounts&lt;br /&gt;
&amp;gt; coldata = BMI[,1]&lt;br /&gt;
&amp;gt; coldata = matrix(NA, nrow=nrow(BMI), ncol=1)&lt;br /&gt;
&amp;gt; coldata[,1] = as.vector(BMI[,1])&lt;br /&gt;
&amp;gt; rownames(coldata) = rownames(BMI)&lt;br /&gt;
&amp;gt; colnames(coldata) = &amp;quot;BMI&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Take a look at coldata&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
coldata&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure that all individuals are in our coldata (information) and also in the data is true&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
all(rownames(coldata) == colnames(cts))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Load data into DESeq format, perform statistical analysis and get results&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; dds &amp;lt;- DESeqDataSetFromMatrix(countData = cts, colData = coldata, design = ~ BMI)&lt;br /&gt;
&amp;gt; dds &amp;lt;- DESeq(dds)&lt;br /&gt;
&amp;gt; res &amp;lt;- results(dds)&lt;br /&gt;
&amp;gt; res&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Order the results according to the adjusted p-value and show the most significant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; resOrdered &amp;lt;- res[order(res$pvalue),]&lt;br /&gt;
&amp;gt; head(resOrdered)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q14. which are the most significant species (google)? Is there an overlap between these and using downsizing+wilcoxon test (what you did above)?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Please find answers [[QuantitativeMetagenomicsSolution|here]]&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=192</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=192"/>
		<updated>2025-01-14T11:17:50Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2025/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2025/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2025/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2025/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2025/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2025/42_post_alignment_variantcalling_part1_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2025/43_post_alignment_variantcalling_part2_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2025/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2025/Long_read_sequencing_Lecture_09-01-2025.pptx Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2025/dtu_adna_2025_red.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]]) &amp;lt;!-- ([[Rnaseq_exercise_answers]]) --&amp;gt; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2025/Genomic_epidemiology_NGScourse_Jan2025.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2025/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2023/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;recap test &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2025])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancer-seq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=191</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=191"/>
		<updated>2025-01-14T10:28:57Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2025/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2025/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2025/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2025/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2025/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2025/42_post_alignment_variantcalling_part1_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2025/43_de_novo_assembly_course_part2_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2025/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2025/Long_read_sequencing_Lecture_09-01-2025.pptx Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2025/dtu_adna_2025_red.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]]) &amp;lt;!-- ([[Rnaseq_exercise_answers]]) --&amp;gt; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2025/Genomic_epidemiology_NGScourse_Jan2025.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2025/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2023/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;recap test &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2025])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancer-seq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=QuantitativeMetagenomics&amp;diff=190</id>
		<title>QuantitativeMetagenomics</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=QuantitativeMetagenomics&amp;diff=190"/>
		<updated>2025-01-13T11:57:41Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&amp;lt;H3&amp;gt;Overview&amp;lt;/H3&amp;gt;&lt;br /&gt;
If you need to use metagenomics for your final project, we have a more thorough workflow that you will need to use [[https://teaching.healthtech.dtu.dk/22136/index.php/22136:Course_plan_autumn_2020 here]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Since metagenomics data is often very large, it requires a lot of computational resources and time, we have cheated a little bit and prepared some data for you in advance!&lt;br /&gt;
&lt;br /&gt;
In this exercise we have done the assembly and counting across a cohort of hundreds of human fecal&lt;br /&gt;
samples in advance and in addition provide the gene-wise taxonomy and the BMI of the&lt;br /&gt;
human donors.&lt;br /&gt;
From this data we shall estimate the species richness, diversity and look at the effect of&lt;br /&gt;
downsizing. Furthermore we shall see if we can identify any differences between the&lt;br /&gt;
microbiome of lean and obese.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Becoming a pirate&amp;lt;/H3&amp;gt;&lt;br /&gt;
This exercise uses R either locally (install RStudio on your own machine) or on the server by typing &lt;br /&gt;
&amp;lt;pre&amp;gt;R&amp;lt;/pre&amp;gt;&lt;br /&gt;
First, IF you are running RStudio locally you will need to install a package called &amp;quot;vegan&amp;quot;&lt;br /&gt;
&amp;lt;pre&amp;gt;install.packages(&amp;quot;vegan&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Now, let’s load the &amp;quot;vegan&amp;quot; package and thereafter load the read count data from a series of stool samples.&lt;br /&gt;
&amp;lt;pre&amp;gt;library(&amp;quot;vegan&amp;quot;)&lt;br /&gt;
load(url(&amp;quot;https://teaching.healthtech.dtu.dk/material/22126/Counts_NGS.RData&amp;quot;))&lt;br /&gt;
head(Counts)&lt;br /&gt;
str(Counts)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Q1. How many samples do we have and how many genes?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The different samples may have been sequenced to different depths. Try to count the reads per sample&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sampleDepth&amp;lt;-(colSums(Counts))&lt;br /&gt;
hist(sampleDepth, breaks=100, ylab=&amp;quot;Number of samples&amp;quot;, xlab=&amp;quot;Number of reads&amp;quot;, main=&amp;quot;Sample depth&amp;quot;)&lt;br /&gt;
range(sampleDepth)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q2. Whats the sample depth range?&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;H3&amp;gt;Species&amp;lt;/H3&amp;gt;&lt;br /&gt;
Lets get the genes associated to species. Here is the gene-wise species taxonomy&lt;br /&gt;
&amp;lt;pre&amp;gt;load(url(&amp;quot;https://teaching.healthtech.dtu.dk/material/22126//taxonomy_species.RData&amp;quot;))&lt;br /&gt;
head(taxonomy_species)&amp;lt;/pre&amp;gt;&lt;br /&gt;
We then combine (by summing) the read counts pr. gene to read counts per species.&lt;br /&gt;
&amp;lt;pre&amp;gt;taxCounts&amp;lt;-apply(Counts, 2, tapply, INDEX=taxonomy_species, sum)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Try looking at the taxCounts matrix&lt;br /&gt;
&amp;lt;pre&amp;gt;str(taxCounts)&lt;br /&gt;
head(taxCounts)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Q3. How many species are there in total?&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;H3&amp;gt;Richness and Diversity&amp;lt;/H3&amp;gt;&lt;br /&gt;
What is the species richness and diversity (Shannon) for the different samples.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q4. What does a high Shannon diversity index mean?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
OK, lets see it for our samples&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
species_richness&amp;lt;-(colSums(taxCounts&amp;gt;0))&lt;br /&gt;
names(species_richness)&amp;lt;-NULL&lt;br /&gt;
require(vegan)&lt;br /&gt;
speciesDiversity&amp;lt;-diversity(t(taxCounts), index = &amp;quot;shannon&amp;quot;)&lt;br /&gt;
names(speciesDiversity)&amp;lt;-NULL &lt;br /&gt;
par(mfrow=c(1,1))&lt;br /&gt;
barplot(sort(species_richness), las=3, main=&amp;quot;Species richness&amp;quot;, xlab=&amp;quot;Samples&amp;quot;, ylab=&amp;quot;Richness&amp;quot;)&lt;br /&gt;
barplot(sort(speciesDiversity), xlab=&amp;quot;Samples&amp;quot;, las=3, main=&amp;quot;Diversity (Shannon)&amp;quot;)&lt;br /&gt;
plot(species_richness,speciesDiversity,xlab=&amp;quot;Richness&amp;quot;, ylab=&amp;quot;Shannon diversity index&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:raw_richness.png]][[File:raw_shannon.png]][[File:raw_richnessVSshannonZoom.png]]&lt;br /&gt;
&lt;br /&gt;
Each samples or persons richness and diversity is shown and the third plot shows each sample/persons richness &amp;amp; diversity as a dot.&lt;br /&gt;
&amp;lt;H3&amp;gt;Downsizing or rarefying&amp;lt;/H3&amp;gt;&lt;br /&gt;
But this was on the raw count data with different sampling depth (number of counts) per sample. We should downsize so that we get fair comparisons.&lt;br /&gt;
&lt;br /&gt;
First suggest the number of reads we should sample per sample for the downsizing [target]. If we chose a low target we will loose abundance resolution and detection sensitivity. If we chose it higher we will loose samples.&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;gt; plot(sampleDepth, pch=20, log=&amp;quot;y&amp;quot;, xlab=&amp;quot;Samples&amp;quot;, ylab=&amp;quot;Number of reads&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:raw_sampledepth.png]]&lt;br /&gt;
&lt;br /&gt;
There is no right answer (but there are less good suggestions). Insert the number you want to downsize to below and plot it again - the samples above the horizontal line we will keep and the samples below the line we will throw out.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; downsizeTarget &amp;lt;- INSERT NUMBER&lt;br /&gt;
&amp;gt; plot(sampleDepth, pch=20, log=&amp;quot;y&amp;quot;, xlab=&amp;quot;Samples&amp;quot;, ylab=&amp;quot;Number of reads&amp;quot;); abline(h=downsizeTarget)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:downsized_sampledepth.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q5. Which threshold did you chose and why? How many samples did you loose?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
OK lets downsize&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; dz_Counts&amp;lt;-round(t(t(Counts)*downsizeTarget/sampleDepth))&lt;br /&gt;
&amp;gt; weak_samples&amp;lt;-sampleDepth&amp;lt;downsizeTarget&lt;br /&gt;
&amp;gt; dz_Counts[,weak_samples]&amp;lt;-NA # samples that did not make the cut&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a quick and dirty downsizing (ideally one resampled the reads to a given depth, but that will take days)&lt;br /&gt;
Count the species again, now on the downsized data.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dz_taxCounts&amp;lt;-apply(dz_Counts, 2, tapply, INDEX=taxonomy_species, sum); gc() &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the richness and diversity again, now on downsized data&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; dz_species_richness&amp;lt;-(colSums(dz_taxCounts&amp;gt;0))&lt;br /&gt;
&amp;gt; names(dz_species_richness)&amp;lt;-NULL&lt;br /&gt;
&amp;gt; require(vegan)&lt;br /&gt;
&amp;gt; dz_speciesDiversity&amp;lt;-diversity(t(dz_taxCounts), index = &amp;quot;shannon&amp;quot;)&lt;br /&gt;
&amp;gt; dz_speciesDiversity[weak_samples]&amp;lt;-NA&lt;br /&gt;
&amp;gt; names(dz_speciesDiversity)&amp;lt;-NULL&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now plot the richness and diversity with downsized data&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; par(mfrow=c(1,1), pch=1)&lt;br /&gt;
&amp;gt; barplot(sort(dz_species_richness), las=3, main=&amp;quot;Species richness (Downsized)&amp;quot;, xlab=&amp;quot;Species&amp;quot;, ylab=&amp;quot;Richness&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:downsized_richness.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
barplot(sort(dz_speciesDiversity), las=3,main=&amp;quot;Shannon&#039;s diversity index (downsized)&amp;quot;, xlab=&amp;quot;Species&amp;quot;, ylab=&amp;quot;Shannon diversity&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:downsized_shannon.png]]&lt;br /&gt;
&lt;br /&gt;
And compare to the raw data&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; plot(dz_species_richness,species_richness, xlab=&amp;quot;downsized richness&amp;quot;, ylab=&amp;quot;raw richness&amp;quot;, main=&amp;quot;Richness&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:Comparing_richness.png]]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; plot(dz_speciesDiversity,speciesDiversity,xlab=&amp;quot;downsized species diversity&amp;quot;, ylab=&amp;quot;raw species diversity&amp;quot;,main=&amp;quot;Diversity (Shannon)&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:Comparing_shannon.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q6. What is the effect on the downsizing on richness&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q7. What is the effect on the downsizing on diversity (shannon)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lets plot the abundance of each species in a sample with low diversity and a sample with high diversity. You should be able to see a clear difference between the two samples!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; par(mfrow=c(1,2))&lt;br /&gt;
&amp;gt; barplot(taxCounts[,4], main=&amp;quot;Person 4, SD &amp;gt; 3&amp;quot;, xaxt=&amp;quot;n&amp;quot;, xlab=&amp;quot;Species&amp;quot;, ylab=&amp;quot;Normalized abundance&amp;quot;)&lt;br /&gt;
&amp;gt; barplot(taxCounts[,240], main=&amp;quot;Person 240, SD &amp;lt; 0.5&amp;quot;, xaxt=&amp;quot;n&amp;quot;, xlab=&amp;quot;Species&amp;quot;, ylab=&amp;quot;Normalized abundance&amp;quot;)&lt;br /&gt;
&amp;gt; par(mfrow=c(1,1))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:comparing_species_abundance.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Comparisons&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now lets see if there is a difference between the microbiome of lean and obese humans. But first load some sample more information: BMI and Class.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; load(url(&amp;quot;https://teaching.healthtech.dtu.dk/material/22126/BMI.RData&amp;quot;))&lt;br /&gt;
&amp;gt; boxplot(BMI$BMI.kg.m2 ~ BMI$Class, col=c(&amp;quot;red&amp;quot;, &amp;quot;gray&amp;quot;,&amp;quot;blue&amp;quot;), ylab=&amp;quot;BMI&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[File:bmi_class.png]]&lt;br /&gt;
&lt;br /&gt;
Class are: le = Lean; ow = Overweight; ob = Obese&lt;br /&gt;
&lt;br /&gt;
First let us see if the abundance of E. coli differs between obese and lean individuals using a Wilcoxon rank sum test (look for the p-value in the output), also lets get the mean abundance of E. coli in the tree groups :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; wilcox.test(x=dz_taxCounts[&amp;quot;Escherichia coli&amp;quot;,BMI$Classification==&amp;quot;ob&amp;quot;], y=dz_taxCounts[&amp;quot;Escherichia coli&amp;quot;,BMI$Classification==&amp;quot;le&amp;quot;] )&lt;br /&gt;
&amp;gt; tapply(dz_taxCounts[&amp;quot;Escherichia coli&amp;quot;,], BMI$Classification, mean, na.rm=TRUE)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q8. Is there any significant difference in abundance of E. coli between the different BMI groups?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s test all species correcting for multiple testing using Benjamini-Hochberg (False Discovery Rate) (we are testing 120 species) and plot them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; pval&amp;lt;-apply(dz_taxCounts, 1, function(V){wilcox.test(x=V[BMI$Classification==&amp;quot;ob&amp;quot;],y=V[BMI$Classification==&amp;quot;le&amp;quot;])$p.value})&lt;br /&gt;
&amp;gt; Abundance_ratio&amp;lt;-log2(apply(dz_taxCounts, 1,function(V){mean(x=V[BMI$Classification==&amp;quot;ob&amp;quot;], na.rm=TRUE)/mean(V[BMI$Classification==&amp;quot;le&amp;quot;], na.rm=TRUE)}))&lt;br /&gt;
&amp;gt; pval.adjust = p.adjust(pval, method=&amp;quot;BH&amp;quot;)&lt;br /&gt;
&amp;gt; plot(sort(pval.adjust), log=&amp;quot;y&amp;quot;, pch=16, xlab=&amp;quot;Species&amp;quot;, ylab=&amp;quot;p-values&amp;quot;)&lt;br /&gt;
&amp;gt; abline(h=0.05, col=&amp;quot;grey&amp;quot;, lty=2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q9. How many species are significant with an false discovery rate &amp;lt; 0.05?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Let us look at the top 10 most significant species abundance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; o&amp;lt;-order(pval)&lt;br /&gt;
&amp;gt; BMIstat&amp;lt;-data.frame(pval,pval.adjust, Abundance_ratio)[o,]&lt;br /&gt;
&amp;gt; BMIstat[1:10,]&lt;br /&gt;
&amp;gt; par(mar=c(5,18,5,5))&lt;br /&gt;
&amp;gt; barplot(BMIstat[1:10,3], names.arg=rownames(BMIstat)[1:10], las=1,xlab=&amp;quot;log fold difference between lean and obese&amp;quot;, horiz=TRUE)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:log_fold_diff_sign.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q10. Can you see any differences in the abundances - which species have large differences, what are their p-values?&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q11. What type of bacteria is the most significant one? [try google]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Beta-diversity and PCA&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Plot the Bray-curtis distance between samples as a heatmap.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
library(RColorBrewer)&lt;br /&gt;
library(gplots)&lt;br /&gt;
vdist = as.matrix(vegdist(t(taxCounts)))&lt;br /&gt;
rownames(vdist) = colnames(vdist)&lt;br /&gt;
hmcol = colorRampPalette(brewer.pal(9, &amp;quot;GnBu&amp;quot;))(100)&lt;br /&gt;
heatmap.2(vdist, trace=&#039;none&#039;, col=rev(hmcol))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q12. Can you see some clusters of samples?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Finally for the PCA:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; my.rda &amp;lt;- rda(t(taxCounts))&lt;br /&gt;
&amp;gt; biplot(my.rda, display = c(&amp;quot;sites&amp;quot;, &amp;quot;species&amp;quot;), type = c(&amp;quot;text&amp;quot;, &amp;quot;points&amp;quot;))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q13. Can you see which species that seems to be driving the differences between the samples?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Statistically modelling the variance using DESeq2&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, we will see the power of statistically modelling the variance instead of downsizing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; if (!requireNamespace(&amp;quot;BiocManager&amp;quot;, quietly = TRUE))&lt;br /&gt;
&amp;gt; install.packages(&amp;quot;BiocManager&amp;quot;)&lt;br /&gt;
&amp;gt; BiocManager::install(&amp;quot;DESeq2&amp;quot;)&lt;br /&gt;
&amp;gt; library(DESeq2)&lt;br /&gt;
&amp;gt; cts &amp;lt;- taxCounts&lt;br /&gt;
&amp;gt; coldata = BMI[,1]&lt;br /&gt;
&amp;gt; coldata = matrix(NA, nrow=nrow(BMI), ncol=1)&lt;br /&gt;
&amp;gt; coldata[,1] = as.vector(BMI[,1])&lt;br /&gt;
&amp;gt; rownames(coldata) = rownames(BMI)&lt;br /&gt;
&amp;gt; colnames(coldata) = &amp;quot;BMI&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Take a look at coldata&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
coldata&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure that all individuals are in our coldata (information) and also in the data is true&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
all(rownames(coldata) == colnames(cts))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Load data into DESeq format, perform statistical analysis and get results&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; dds &amp;lt;- DESeqDataSetFromMatrix(countData = cts, colData = coldata, design = ~ BMI)&lt;br /&gt;
&amp;gt; dds &amp;lt;- DESeq(dds)&lt;br /&gt;
&amp;gt; res &amp;lt;- results(dds)&lt;br /&gt;
&amp;gt; res&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Order the results according to the adjusted p-value and show the most significant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; resOrdered &amp;lt;- res[order(res$pvalue),]&lt;br /&gt;
&amp;gt; head(resOrdered)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q14. which are the most significant species (google)? Is there an overlap between these and using downsizing+wilcoxon test (what you did above)?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Please find answers [[QuantitativeMetagenomicsSolution|here]]&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=189</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=189"/>
		<updated>2025-01-13T10:47:45Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2025/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2025/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2025/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2025/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2025/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2025/42_post_alignment_variantcalling_part1_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2025/43_de_novo_assembly_course_part2_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2025/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2025/Long_read_sequencing_Lecture_09-01-2025.pptx Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2025/dtu_adna_2025_red.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]]) &amp;lt;!-- ([[Rnaseq_exercise_answers]]) --&amp;gt; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2025/Genomic_epidemiology_NGScourse_Jan2025.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2025/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2024/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;recap test &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2025])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancer-seq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=188</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=188"/>
		<updated>2025-01-09T11:20:14Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2025/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2025/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2025/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2025/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2024/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2024/42_post_alignment_variantcalling_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2024/Long_read_sequencing_Lecture_08-01-2023.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2024/dtu_adna_2024.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]]) &amp;lt;!-- ([[Rnaseq_exercise_answers]]) --&amp;gt; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2024/Genomic_epidemiology_NGScourse_Jan2024.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2024/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2024/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;recap test &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2025])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancer-seq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=187</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=187"/>
		<updated>2025-01-09T11:19:27Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2025/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2025/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2025/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2025/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2024/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2024/42_post_alignment_variantcalling_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2024/Long_read_sequencing_Lecture_08-01-2023.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2024/dtu_adna_2024.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]]) &amp;lt;!-- ([[Rnaseq_exercise_answers]]) --&amp;gt; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2024/Genomic_epidemiology_NGScourse_Jan2024.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2024/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2024/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;recap test &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2024])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancer-seq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Denovo_exercise&amp;diff=186</id>
		<title>Denovo exercise</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Denovo_exercise&amp;diff=186"/>
		<updated>2025-01-09T09:59:27Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;H2&amp;gt;Overview&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
First:&lt;br /&gt;
&amp;lt;OL&amp;gt;&lt;br /&gt;
&amp;lt;LI&amp;gt;Navigate to your home directory:&lt;br /&gt;
&amp;lt;LI&amp;gt;Create a directory called &amp;quot;denovo&amp;quot; &lt;br /&gt;
&amp;lt;LI&amp;gt;Navigate to the directory you just created.&lt;br /&gt;
&amp;lt;/OL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;In this exercise we will try to perform de novo assembly of Illumina paired-end reads. The data is from a &amp;lt;i&amp;gt;Vibrio cholerae&amp;lt;/i&amp;gt; strain isolated in Nepal. You will try to:&lt;br /&gt;
&amp;lt;OL&amp;gt;&lt;br /&gt;
   &amp;lt;LI&amp;gt;Run FastQC, adaptor and quality trimming reads (Optional - repeat of analysis you have already done in data pre-processing)&lt;br /&gt;
   &amp;lt;LI&amp;gt;Count k-mers and estimate genome size&lt;br /&gt;
   &amp;lt;LI&amp;gt;Correct reads using Musket&lt;br /&gt;
   &amp;lt;LI&amp;gt;Determine insert size of paired-end reads&lt;br /&gt;
   &amp;lt;LI&amp;gt;Run de novo assembly using MEGAHIT&lt;br /&gt;
   &amp;lt;LI&amp;gt;Calculate assembly statistics&lt;br /&gt;
   &amp;lt;LI&amp;gt;Plot coverage and length histograms of the assembly&lt;br /&gt;
   &amp;lt;LI&amp;gt;Assembly evaluation&lt;br /&gt;
   &amp;lt;LI&amp;gt;Visualize assembly using Circoletto&lt;br /&gt;
   &amp;lt;LI&amp;gt;Try to assemble the genome using SPAdes (bonus)&lt;br /&gt;
   &amp;lt;LI&amp;gt;Assembly of PacBio and NanoPore&lt;br /&gt;
&amp;lt;/OL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;FastQC and trimming&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make sure you are in the &amp;quot;denovo&amp;quot; directory you created, you can double-check with the following command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pwd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
go ahead and copy the sequencing data&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /home/projects/22126_NGS/exercises/denovo/vchol/* .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Let us start by running fastqc on the reads:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir fastqc&lt;br /&gt;
fastqc -o fastqc *.txt.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Open the reports in firefox.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
firefox fastqc/Vchol-001_6_1_sequence_fastqc.html fastqc/Vchol-001_6_2_sequence_fastqc.html &amp;amp;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;There are quite some issues with this data (but do not spend to much time on studying the report), we should clean it up first. Let us find out what type of encoding the qualities are in:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gzip -dc Vchol-001_6_1_sequence.txt.gz | fastx_detect_fq.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Q1. Which format are they encoded in?&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Let us trim the reads using AdapterRemoval. In the command below the most frequent adapter/primer sequence is already pasted in - do not worry about the others in our case they are just variations of that one. Also, we use a minimum of 40 nt and trim to quality 20 (~3 mins) and note that we write qualitybase 64 (Q1). The &amp;quot;--basename&amp;quot; option gives the base name of the output files and we want it to be compressed using gzip &amp;quot;--gzip&amp;quot;. When it is done take a look at &amp;quot;Vchol-001_6.settings&amp;quot; for some statistics on how many reads were trimmed etc.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
AdapterRemoval --file1 Vchol-001_6_1_sequence.txt.gz --file2 Vchol-001_6_2_sequence.txt.gz --adapter1 GATCGGAAGAGCACACGTCTGAACTCCAGTCACATCACGATATCGTATGC --adapter2 GATCGGAAGAGCGTCGTGTAGGGAAAGAGGGTAGATCTCGGTGGTCGCCG --qualitybase 64 --basename Vchol-001_6 --gzip --trimqualities --minquality 20 --minlength 40&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q1A.  There are several output files (discarded.gz, pair1.truncated.gz, pair2.truncated.gz, singleton.truncated.gz), can you explain which files contains which reads? (tip: look for documentation online)&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Ok, now we have our reads trimmed and ready to go. Count stats of the trimmed data such as average read length, min length, max length, no. reads and no. bases. Note down the avg readlength and the no. of bases.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python2 /home/ctools/misc_scripts/fastx_readlength.py --i Vchol-001_6.pair1.truncated.gz --gz&lt;br /&gt;
python2 /home/ctools/misc_scripts/fastx_readlength.py --i Vchol-001_6.pair2.truncated.gz --gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Genome size estimation&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt; Let&#039;s try to count the occurrence of k-mers in the data - a k-mer is simply a string of nucleotides of a certain length. Let&#039;s say we count all the 15-mers that are in the read data we have - we do this using a program called [http://www.cbcb.umd.edu/software/jellyfish/jellyfish-manual.html jellyfish]. Here we tell jellyfish to count 15-mers and also add counts from the complementary strand. Afterward, we tell it to create a histogram that we will plot using R. &amp;quot;/dev/fd/0&amp;quot; in the command below means that it should take input from &amp;quot;STDIN&amp;quot;, eg. from the gzip program.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gzip -dc Vchol-001_6.pair*.truncated.gz | jellyfish count -t 2 -m 15 -s 1000000000 -o Vchol-001 -C /dev/fd/0&lt;br /&gt;
jellyfish histo Vchol-001 &amp;gt; Vchol-001.histo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we call R:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
R&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and paste the following to generate a histogram:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dat=read.table(&amp;quot;Vchol-001.histo&amp;quot;)&lt;br /&gt;
barplot(dat[,2], xlim=c(0,150), ylim=c(0,5e5), ylab=&amp;quot;No of kmers&amp;quot;, xlab=&amp;quot;Counts of a k-mer&amp;quot;, names.arg=dat[,1], cex.names=0.8)&lt;br /&gt;
dev.print(&amp;quot;Vchol-001.histo.pdf&amp;quot;, device=pdf)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The plot shows how many times a k-mer is found (x-axis) and the number of kmers with this count (y-axis). The bars in the lower end are the k-mers that only occur very few times, these are probably sequencing errors, whereas the k-mers that occur many times are &amp;quot;real&amp;quot; k-mers. We can use the information from the &amp;quot;real&amp;quot; k-mers to correct similar &amp;quot;error k-mers&amp;quot;. In this way we can increase the performance of our assembly (this also works for SNP calling as well).&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q2. Where is the peak for the kmers?&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Before we perform error correction on the reads, we will try to estimate the genome size of our genome. Of course, we know that it is a V. cholerae, but if we did not know that or it was an unknown species then we could do like this. N = (M*L)/(L-K+1) and Genome_size = T/N, where N: Depth, M: Kmer peak, K: Kmer-size, L: avg readlength, T: Total bases. Try to put in the numbers (some of them you have from &amp;quot;fastx_readlength.py&amp;quot; command) and see what you get. The reference vibrio cholerae genome is around 4Mb, you should get within +/- 10% of this.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Q3. What is the estimated genome size?&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Error correction&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Let us try to correct the reads using [http://musket.sourceforge.net/homepage.htm Musket]. First we need to know how many k-mers will be in the data, this is rather easy to get because we already counted kmers using jellyfish. Use this command to output the number of &amp;quot;distinct&amp;quot; k-mers in the dataset:&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
jellyfish stats Vchol-001&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This is needed for musket to set up the bloom filters and hash tables for memory consumption. Then we are ready to run the correction. &amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
musket -k 15 8423098 -p 1 -omulti Vchol-001_6.cor -inorder Vchol-001_6.pair1.truncated.gz Vchol-001_6.pair2.truncated.gz -zlib 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The files do not have an ideal name. Finally, we will rename the output files to sensible names.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mv Vchol-001_6.cor.0 Vchol-001_6.pair1.cor.truncated.fq.gz&lt;br /&gt;
mv Vchol-001_6.cor.1 Vchol-001_6.pair2.cor.truncated.fq.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;If this takes a long time copy my files:&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /home/projects/22126_NGS/exercises/denovo/vchol/corrected/Vchol-001_6.pair*.cor.truncated.fq.gz .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;&amp;lt;i&amp;gt;de novo&amp;lt;/i&amp;gt; assembly&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Now the reads are ready for &amp;lt;i&amp;gt;de novo&amp;lt;/i&amp;gt; assembly. We are going to use MEGAHIT as our assembler, it uses the de Bruijn approach. When running &#039;&#039;de novo&#039;&#039; assemblies one should try different k-mer sizes - the k-mer size is used for building the de Bruijn graph and is therefore very important. There is currently no way to estimate what will be the optimal k before running, the best k-size may change between different datasets and may change between different assemblers for the same dataset. By default, MEGAHIT tried different kmer length values. But we can set a fixed kmer length as well&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;We will try first with a fixed kmer length of &amp;lt;b&amp;gt;35 bases&amp;lt;/b&amp;gt;. &amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export OMP_NUM_THREADS=4 &lt;br /&gt;
/home/ctools/MEGAHIT-1.2.9/bin/megahit -1 Vchol-001_6.pair1.cor.truncated.fq.gz -2 Vchol-001_6.pair2.cor.truncated.fq.gz  --k-list 35  -t 4 -m 2000000000 -o 35&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The first command with OMP_NUM_THREADS is to allow more threads to be used. The flags -1 -2 specify the paired-end files. The kmer length is specified with --k-list but we could specify multiple values ex --k-list 35,39. The number of threads is -t 4 and memory is 2G (-m 2000000000). The output directory is 35/ in your current working directory. &amp;lt;/p&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;p&amp;gt;Now you should have a file called &amp;quot;35/final.contigs.fa&amp;quot;. It is unzipped so let&#039;s zip it:&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gzip 35/final.contigs.fa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt; we need to map our reads back to the contigs to identify the insert size, just as we did in the alignment exercise. Let us only map the first 100.000 reads - this should be enough.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zcat Vchol-001_6.pair1.cor.truncated.fq.gz | head -n 400000 |gzip &amp;gt; Vchol_sample_1.fastq.gz&lt;br /&gt;
zcat Vchol-001_6.pair2.cor.truncated.fq.gz | head -n 400000 |gzip &amp;gt; Vchol_sample_2.fastq.gz&lt;br /&gt;
&lt;br /&gt;
bwa index 35/final.contigs.fa.gz&lt;br /&gt;
bwa mem 35/final.contigs.fa.gz Vchol_sample_1.fastq Vchol_sample_2.fastq | samtools view -Sb - &amp;gt; Vchol_35bp.bam&lt;br /&gt;
&lt;br /&gt;
samtools view Vchol_35bp.bam | cut -f9 &amp;gt; initial.insertsizes.txt&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then use R:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
R&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and paste:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
a = read.table(&amp;quot;initial.insertsizes.txt&amp;quot;)&lt;br /&gt;
a.v = a[a[,1]&amp;gt;0,1]&lt;br /&gt;
mn = quantile(a.v, seq(0,1,0.05))[4]&lt;br /&gt;
mx = quantile(a.v, seq(0,1,0.05))[18]&lt;br /&gt;
mean(a.v[a.v &amp;gt;= mn &amp;amp; a.v &amp;lt;= mx])       # mean&lt;br /&gt;
sd(a.v[a.v &amp;gt;= mn &amp;amp; a.v &amp;lt;= mx])         # sd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q4. What are the mean insert size and standard deviation of our library?&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;We will now try different values of k. We will all choose a different k-mer to run and then we will compare to find the &amp;quot;best&amp;quot; assembly.Chose one of the K-sizes on the [https://docs.google.com/spreadsheets/d/1DjfbriqIEuCq8FMRLlt69ITpgm2NKcmZzun11-T43HQ/edit?usp=sharing Google sheet] and change the &amp;quot;XX&amp;quot; values below to your number. Remember to write your name in the document. Then use the kmer length as [KMER LENGTH HERE] here:&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export OMP_NUM_THREADS=4 &lt;br /&gt;
/home/ctools/MEGAHIT-1.2.9/bin/megahit -1 Vchol-001_6.pair1.cor.truncated.fq.gz -2 Vchol-001_6.pair2.cor.truncated.fq.gz  --k-list [KMER LENGTH HERE]  -t 4 -m 2000000000 -o [KMER LENGTH HERE]&lt;br /&gt;
gzip  [KMER LENGTH HERE]/final.contigs.fa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;When it is done, we need to calculate some statistics on it, there is a script from the Assemblathon (a competition for assemblers) that does it &amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assemblathon_stats.pl [KMER LENGTH HERE]/final.contigs.fa &amp;gt; [KMER LENGTH HERE]/final.contigs.stats&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Open the [KMER LENGTH HERE]/final.contigs.stats file and fill in the information in the Google sheet for your respective length of k. We will then compare the results and find the best K-size for the particular dataset.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Copy the best assembly to your folder and use this assembly from now on. You can also use a fairly good one I made previously using default parameters so multiple values of k.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /home/projects/22126_NGS/exercises/denovo/best/default_final.contigs.fa.gz .&lt;br /&gt;
cp /home/projects/22126_NGS/exercises/denovo/best/default_final.contigs.stats .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q5. How does the N50 of the assembly compare with what we got using fixed kmers?&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q6. How does the longest contig of the assembly compare with what we got using fixed kmers?&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Coverage of assembly&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt; Let&#039;s calculate the coverage and length for each sequence and plot it as a histogram in R. We also plot the lengths of the scaffolds.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zcat default_final.contigs.fa.gz | fastx_megahit.py --i /dev/stdin &amp;gt; default_finalt.cov&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then use R:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
R&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and write the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
library(plotrix)&lt;br /&gt;
dat=read.table(&amp;quot;default_finalt.cov&amp;quot;, sep=&amp;quot;\t&amp;quot;)&lt;br /&gt;
par(mfrow=c(1,2))&lt;br /&gt;
weighted.hist(w=dat[,2], x=dat[,1], breaks=seq(0,100, 1), main=&amp;quot;Weighted coverage&amp;quot;, xlab=&amp;quot;Contig coverage&amp;quot;)&lt;br /&gt;
hist(dat[,1], xlim=c(0,100), breaks=seq(0,1000,1), main=&amp;quot;Raw coverage&amp;quot;, xlab=&amp;quot;Contig coverage&amp;quot;)&lt;br /&gt;
dev.print(&amp;quot;best.coverage.pdf&amp;quot;, device=pdf)&lt;br /&gt;
&lt;br /&gt;
# Lengths&lt;br /&gt;
par(mfrow=c(1,1))&lt;br /&gt;
barplot(rev(sort(dat[,2])), xlab=&amp;quot;# Scaffold&amp;quot;, ylab=&amp;quot;Length&amp;quot;, main=&amp;quot;Scaffold Lengths&amp;quot;)&lt;br /&gt;
dev.print(&amp;quot;scaffold.lengths.pdf&amp;quot;, device=pdf)&lt;br /&gt;
q(save=&amp;quot;no&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
evince best.coverage.pdf &amp;amp;&lt;br /&gt;
evince scaffold.lengths.pdf &amp;amp;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The left plot shows the length-weighted coverage (of k-mers) of the contigs/scaffolds - this means that long sequences have a larger weight compared to short sequences. The plot on the right side shows a normal histogram of contig coverage. By comparing the two plots we see that the majority of the assembly has a k-mer coverage of around 60-90X, and that the remaining assembly are short sequences. NB: The contig coverage is dependent on the size of the K you chose. Looking at the plot with the lengths you see that the majority of the assembly is in quite long scaffolds.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q7. Can you think of why some short contigs have much higher coverage compared to the main assembly?&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q8. Can you think of why some short contigs have much lower coverage compared to the main assembly?&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Assembly evaluation&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;First we will use Quast to evaluate the assembly using different metrics, see [http://bioinf.spbau.ru/quast quast]. You can run it with our without a reference genome and we will try to evaluate our assembly vs. the Vibrio cholerae reference genome:&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python /home/ctools/quast-quast_5.0.2/quast.py default_final.contigs.fa.gz -R /home/projects/22126_NGS/exercises/denovo/reference/vibrio_cholerae_O1_N16961.fa&lt;br /&gt;
firefox quast_results/latest/report.html &amp;amp; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q9. You can see in the report that there are some misassemblies - can we always trust this?&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Visualization using circoletto&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt; Let&#039;s try to visualize the assembly. Because we know that the data is from a &amp;lt;i&amp;gt;Vibrio cholerae&amp;lt;/i&amp;gt; we can try to compare our assembly with the V.cholerae reference genome. First, let&#039;s filter the assembly to a minimum of 500bp.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fastx_filterfasta.py --i default_final.contigs.fa.gz --min 500&lt;br /&gt;
gunzip default_final.contigs.fa.gz.filtered_500.fa.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;We need to unzip to use gedit. Open a browser on your own computer and go to the [https://bat.infspire.org/circoletto/ Circoletto webpage]. Circoletto is an easy-to-use web program that builds upon Circos - a program to create amazing plots with genomic (and other) data. Open the filtered assembly (&amp;lt;b&amp;gt;&amp;quot;gedit default_final.contigs.fa.gz.filtered_500.fa &amp;amp;&amp;quot;&amp;lt;/b&amp;gt;) select all and copy-paste it into the upper box (query fasta). Do the same with the reference genome (&amp;lt;b&amp;gt;&amp;quot;gedit /home/projects/22126_NGS/exercises/denovo/reference/vibrio_cholerae_O1_N16961.fa &amp;amp;&amp;quot;&amp;lt;/b&amp;gt;) and copy-paste it into the box just below. In the &amp;quot;output&amp;quot; section click the &amp;quot;ONLY show the best hit per query&amp;quot; and click &amp;quot;submit to Circoletto&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If it does not work, feel free to use: /home/projects/22126_NGS/exercises/denovo/circoletto_results/cl0011524231.blasted.png&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
If it doesn&#039;t work you can download the [http://www.cbs.dtu.dk/courses/27626/misc/Vchol-001.best.fa assembly] and [http://www.cbs.dtu.dk/courses/27626/misc/vibrio_cholerae_O1_N16961.fa reference] that I made.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;If everything fails you can see [http://www.cbs.dtu.dk/courses/27626/misc/circoletto.png this file].&amp;lt;/p&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;You should see the two chromosomes of &amp;lt;i&amp;gt;V. cholerae&amp;lt;/i&amp;gt; on the left-hand side of the figure (named &amp;quot;gi|...&amp;quot;) and then the alignment of our assembly to it. The color of the alignments are the bitscores, the red is the most confident and black, the least confident.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q10. Do you think that our genome is similar to the reference genome?&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q11. Are there scaffolds/contigs that do not or only partially map to the reference genome?&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Q12. What do you think the region on chromosome 2 (the small one) with many small low-confident mappings could be? Hint: See the [https://www.nature.com/articles/35020000 V. cholerae genome paper] and search for &amp;quot;V. cholerae integron island&amp;quot;?&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Try to assemble the genome using SPAdes (bonus)&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;There is a lot of discussions on which assembler is better than others. [http://bioinf.spbau.ru/spades SPAdes] is definitely one of the best ones. SPAdes will run error correction and use multiple k-mers at the same time when it is doing the assembly. Try it out, it is in the bin folder - try to figure out the commands you need to write to run it and compare it with the output from MEGAHIT (hint: you can use Quast for the comparison).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
spades.py -h&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;To run it:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ln -s Vchol-001_6.pair1.cor.truncated.gz Vchol-001_6.pair1.cor.truncated.fastq.gz&lt;br /&gt;
ln -s Vchol-001_6.pair2.cor.truncated.gz Vchol-001_6.pair2.cor.truncated.fastq.gz&lt;br /&gt;
&lt;br /&gt;
spades.py --careful --pe1-1 Vchol-001_6.pair1.cor.truncated.fastq.gz --pe1-2 Vchol-001_6.pair2.cor.truncated.fastq.gz -o spades -t 1 -m 3 --cov-cutoff auto&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;NB: The assembly takes 45 minutes to run with SPAdes, you can therefore use my assembly, try to calculate assembly stats (assemblathon_stats.pl) and run it in Quast together with the SOAPdenovo assembly. To get my assembly:&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s /home/projects/22126_NGS/exercises/denovo/vchol/spades/spades.fasta spades.fasta .&lt;br /&gt;
# you write the code from here&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
assemblathon_stats.pl spades/scaffolds.fasta &amp;gt; spades/scaffolds.stats&lt;br /&gt;
paste spades/scaffolds.stats asmK55.scafSeq.stats | less -S&lt;br /&gt;
# quite many fewer contigs for spades and higher mean contig length&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Assembly of PacBio and NanoPore data&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;For the PacBio and NanoPore data, we are going to use [https://github.com/marbl/canu canu]. Canu is a further development of the Celera assembler which was one of the assemblers used for the original human genome - here they used Sanger reads which are long and have low error rate. Canu has been changed to run with long reads with errors in them.&amp;lt;br&amp;gt;&lt;br /&gt;
Let&#039;s try to run it on some E. coli K12 data. Here we only run it with either PacBio or NanoPore, but it can also handle combinations of these and Illumina. The commands are quite slow&amp;lt;p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# pacbio&lt;br /&gt;
ln -s /home/projects/22126_NGS/exercises/denovo/canu/pacbio.fastq.gz .&lt;br /&gt;
canu -p ecoli_pacbio -d ecoli_pacbio genomeSize=4.8m -pacbio-raw pacbio.fastq.gz -maxThreads=4&lt;br /&gt;
&lt;br /&gt;
# oxford nanopore&lt;br /&gt;
ln -s /home/projects/22126_NGS/exercises/denovo/canu/oxford.fasta.gz .&lt;br /&gt;
canu -p ecoli_nanopore -d ecoli_nanopore genomeSize=4.8m -nanopore-raw oxford.fasta.gz -maxThreads=4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;It is very likely going to take quite some time so you can copy my files:&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ln -s /home/projects/22126_NGS/exercises/denovo/canu/ecoli_pacbio.contigs.fasta .&lt;br /&gt;
ln -s /home/projects/22126_NGS/exercises/denovo/canu/ecoli_nanopore.contigs.fasta .&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Try to count the number of contigs and their length of them (you can see that from the headers):&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
grep &amp;quot;&amp;gt;&amp;quot; [input fasta here]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or &lt;br /&gt;
&amp;lt;pre&amp;gt; &lt;br /&gt;
zgrep &amp;quot;&amp;gt;&amp;quot; [zipped input fasta here]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
python quast.py ecoli_pacbio.contigs.fasta ecoli_nanopore.contigs.fasta  -R /home/projects/22126_NGS/exercises/denovo/canu/ecoli_K12.fa &lt;br /&gt;
firefox quast_results/latest/report.html &amp;amp; &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;Q13. How good are the assemblies using Nanopore and pacbio?&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Annotation of a prokaryotic genome&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will use [https://bmcbioinformatics.biomedcentral.com/articles/10.1186/1471-2105-11-119 prodigal ] to annotate our genes in ecoli_pacbio.contigs.fasta:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/home/ctools/prokka/binaries/linux/prodigal -f gff -i [input genome in fasta] -a [output proteins in fasta] -o [output annotations in gff]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;-f&amp;quot; specifies the output format and &amp;quot;-o&amp;quot; the output file. The output is in [https://www.ensembl.org/info/website/upload/gff.html gff] format for the annotation. The proteins are specified by &amp;quot;-a&amp;quot; and are in FASTA format. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s use a gene that was found and identify what it is as an example. First index the FASTA file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools faidx ecoli_pacbio.contigs.aa  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then find the following gene ID &amp;quot;tig00000001_4582&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools faidx ecoli_pacbio.contigs.aa   tig00000001_4582&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use [https://blast.ncbi.nlm.nih.gov/Blast.cgi?PROGRAM=blastp&amp;amp;PAGE_TYPE=BlastSearch&amp;amp;LINK_LOC=blasthome BLAST for proteins ] and determine which protein it is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt; Q14. Which protein is it? &amp;lt;/b&amp;gt; &amp;lt;BR&amp;gt;&lt;br /&gt;
&amp;lt;HR&amp;gt; &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;H3&amp;gt;Illumina assembly correction (optional)&amp;lt;/H3&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Let us instead try to use [http://www.sanger.ac.uk/science/tools/reapr Reapr]  to evaluate the internal quality of the assembly. It will map our reads back to the assembly and try to identify misassemblies from it. It works best using long insert libraries (&amp;gt;1000 bp) and ours is not that large, but we can try anyway. First, it will map our reads to the assembly using &amp;lt;a href=&amp;quot;http://www.sanger.ac.uk/science/tools/smalt-0&amp;quot;&amp;gt;smalt&amp;lt;/a&amp;gt; and afterward use the read mapping to calculate Fragment Coverage Distribution (FCD) to identify breakpoints in the assembly. &amp;lt;b&amp;gt;It takes a bit of time to run so you could do the Visualization using circoletto while it is running. Eg, run these commands and continue while they are running (open a new terminal or run it in &amp;quot;screen&amp;quot;).&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
reapr facheck Vchol-001.best.fa Vchol-001.best.facheck&lt;br /&gt;
gzip -dc Vchol-001_6.pair1.cor.truncated.gz &amp;gt; Vchol-001_6.pair1.cor.truncated&lt;br /&gt;
gzip -dc Vchol-001_6.pair2.cor.truncated.gz &amp;gt; Vchol-001_6.pair2.cor.truncated&lt;br /&gt;
reapr smaltmap Vchol-001.best.facheck.fa Vchol-001_6.pair1.cor.truncated Vchol-001_6.pair2.cor.truncated Vchol-001.best.bam&lt;br /&gt;
reapr pipeline Vchol-001.best.facheck.fa Vchol-001.best.bam reapr_results&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;When it is done will have generated a summary (reapr_results/05.summary.report.txt) and a broken assembly (reapr_results/04.break.broken_assembly.fa).&amp;lt;/p&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Please find answers [[Denovo_solution|here]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Congratulations you finished the exercise!&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_answers_part_2&amp;diff=185</id>
		<title>SNP calling exercise answers part 2</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_answers_part_2&amp;diff=185"/>
		<updated>2025-01-08T12:26:42Z</updated>

		<summary type="html">&lt;p&gt;Gabre: Created page with &amp;quot; &amp;#039;&amp;#039;&amp;#039;Q1&amp;#039;&amp;#039;&amp;#039;  First running:  &amp;lt;pre&amp;gt; gatk VariantFiltration     -V NA24694.vcf.gz  -O NA24694_hf.vcf.gz   -filter &amp;quot;DP &amp;lt; 10.0&amp;quot; --filter-name &amp;quot;DP&amp;quot;    -filter &amp;quot;QUAL &amp;lt; 30.0&amp;quot; --filter-name &amp;quot;QUAL30&amp;quot;     -filter &amp;quot;SOR &amp;gt; 3.0&amp;quot; --filter-name &amp;quot;SOR3&amp;quot;     -filter &amp;quot;FS &amp;gt; 60.0&amp;quot; --filter-name &amp;quot;FS60&amp;quot;     -filter &amp;quot;MQ &amp;lt; 40.0&amp;quot; --filter-name &amp;quot;MQ40&amp;quot;          &amp;lt;/pre&amp;gt;  and   &amp;lt;pre&amp;gt;  bcftools view  -H NA24694_hf.vcf.gz |grep -v PASS |wc -l  &amp;lt;/pre&amp;gt;  Gives us 4005 sites.  &amp;lt;pre&amp;gt;  bcftools view  -H  --type=...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;Q1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First running:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk VariantFiltration     -V NA24694.vcf.gz  -O NA24694_hf.vcf.gz   -filter &amp;quot;DP &amp;lt; 10.0&amp;quot; --filter-name &amp;quot;DP&amp;quot;    -filter &amp;quot;QUAL &amp;lt; 30.0&amp;quot; --filter-name &amp;quot;QUAL30&amp;quot;     -filter &amp;quot;SOR &amp;gt; 3.0&amp;quot; --filter-name &amp;quot;SOR3&amp;quot;     -filter &amp;quot;FS &amp;gt; 60.0&amp;quot; --filter-name &amp;quot;FS60&amp;quot;     -filter &amp;quot;MQ &amp;lt; 40.0&amp;quot; --filter-name &amp;quot;MQ40&amp;quot;      &lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 bcftools view  -H NA24694_hf.vcf.gz |grep -v PASS |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gives us 4005 sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 bcftools view  -H  --type=snps NA24694_hf.vcf.gz |grep -v PASS |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
2630 SNPs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
One possibility is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 bcftools view -H NA24694_hf.vcf.gz |grep -v PASS |cut -f 7  |sort |uniq -c  |sort -n &lt;br /&gt;
      5 FS60;SOR3&lt;br /&gt;
     30 DP;MQ40;SOR3&lt;br /&gt;
     74 MQ40;SOR3&lt;br /&gt;
    158 DP;SOR3&lt;br /&gt;
    197 DP;MQ40&lt;br /&gt;
    390 MQ40&lt;br /&gt;
   1340 SOR3&lt;br /&gt;
   1811 DP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This says remove all lines with the string &amp;quot;PASS&amp;quot;, extract the seventh column, sort them, unique and count them, sort again but according to numerical order. At the bottom, you have the most used filter which is depth of coverage.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we isolate the ones that pass the filter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view  -f PASS NA24694_hf.vcf.gz |bgzip -c  &amp;gt; NA24694_hf_pass.vcf.gz&lt;br /&gt;
bcftools view -H NA24694_hf_pass.vcf.gz |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
88594 total sites (SNPS+indels+multi-allelic).&lt;br /&gt;
&lt;br /&gt;
Then we retain the sites using bedtools:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bedtools intersect -header -a  NA24694_hf_pass.vcf.gz  -b /home/databases/databases/GRCh38/filter99.bed.gz |bgzip -c &amp;gt; NA24694_hf_map99.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view -H NA24694_hf_map99.vcf.gz |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
51624 total sites remain&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q4&#039;&#039;&#039;&lt;br /&gt;
Using:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
java -jar /home/ctools/snpEff/snpEff.jar  eff  -dataDir /home/databases/databases/snpEff/  -htmlStats NA24694_hf.html GRCh38.99 NA24694_hf.vcf.gz  |bgzip -c &amp;gt; NA24694_hf_ann.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the HTML file you see:&lt;br /&gt;
Intron 64.368% &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q5&#039;&#039;&#039;&lt;br /&gt;
In the HTML file you see:&lt;br /&gt;
&lt;br /&gt;
MISSENSE 584 	44.242% &lt;br /&gt;
&lt;br /&gt;
So a total of 584 detecting mutations can have an impact on the protein sequence.&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=184</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=184"/>
		<updated>2025-01-07T14:42:46Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2025/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2025/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2025/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2025/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2025/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2024/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2024/42_post_alignment_variantcalling_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2024/Long_read_sequencing_Lecture_08-01-2023.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2024/dtu_adna_2024.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]]) &amp;lt;!-- ([[Rnaseq_exercise_answers]]) --&amp;gt; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2024/Genomic_epidemiology_NGScourse_Jan2024.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2024/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2024/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;recap test &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2024])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Astrid Brix Saksager, Grigorii Nos &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Astrid Brix Saksager, Grigorii Nos&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancerseq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Alignment_exercise&amp;diff=183</id>
		<title>Alignment exercise</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Alignment_exercise&amp;diff=183"/>
		<updated>2025-01-07T13:30:19Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H2&amp;gt;Overview&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First:&lt;br /&gt;
&amp;lt;OL&amp;gt;&lt;br /&gt;
&amp;lt;LI&amp;gt;Navigate to your home directory:&lt;br /&gt;
&amp;lt;LI&amp;gt;Create a directory called &amp;quot;align&amp;quot; &lt;br /&gt;
&amp;lt;LI&amp;gt;Navigate to the directory you just created.&lt;br /&gt;
&amp;lt;/OL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will try to align different types of NGS data. &lt;br /&gt;
# &amp;lt;i&amp;gt;Pseudomonas alcaligenes&amp;lt;/i&amp;gt; single-end Illumina reads&lt;br /&gt;
# Human single-end paired-end Illumina reads&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H2&amp;gt;&amp;lt;i&amp;gt;P. aeruginosa&amp;lt;/i&amp;gt; single-end Illumina reads&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Alignment using bwa mem&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt; We will align some of the single-end reads that we trimmed from &amp;lt;i&amp;gt;P. aeruginosa&amp;lt;/i&amp;gt;. The raw data can be found here:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/home/projects/22126_NGS/exercises/alignment/SRR8002634_1.fastq.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The trimmed data can be found here:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/home/projects/22126_NGS/exercises/alignment/SRR8002634_1_trimmed.fq.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The reference genome can be found here:&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 /home/databases/references/P_aeruginosa/GCF_000006765.1_ASM676v1_genomic.fasta &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt; the basic command line to align the data using &#039;&#039;&#039;bwa mem&#039;&#039;&#039; is&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bwa mem  [reference genome in fasta]  [input.fastq.gz] &amp;gt; [output.sam] &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember that the &#039;&#039;&#039;&amp;gt;&#039;&#039;&#039; the operator sends the STDOUT to a file. &lt;br /&gt;
&lt;br /&gt;
We have learned about multiplexing. Get used to adding reads groups to denote the read group ID and sample they belong to. For instance, let us say that our read group was &amp;quot;RG38&amp;quot; and the sample was &amp;quot;SMPL96&amp;quot;. We would add the read groups as such during the alignment:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bwa mem -R &amp;quot;@RG\tID:RG38\tSM:SMPL96&amp;quot; [reference genome in fasta]  [input.fastq.gz] &amp;gt; [output.sam] &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That way, when merging multiple bam files, we know which reads came from which files.&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Align&#039;&#039;&#039; the correct fastq file using the command above.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q1:&#039;&#039;&#039; Had we not told you which fastq file contains the trimmed reads, how could have figured out which file contains the trimmed reads?  I can think of 3 different ways. &lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Looking at the alignment&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First, let us look at the alignment, let us assume you called the output &#039;&#039;&#039;SRR8002634_1.sam&#039;&#039;&#039;. The file can be viewed as such:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
less -S SRR8002634_1.sam&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
-S wraps the lines around, press &#039;q&#039; to quit. Please refer to the slides of the [https://samtools.github.io/hts-specs/SAMv1.pdf official documentation] check what each field means. Answer the following questions:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q2:&#039;&#039;&#039; how many lines does the header have?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q3:&#039;&#039;&#039; what is the genomic coordinate of the first read (SRR8002634.1)?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q4:&#039;&#039;&#039; what is the mapping quality of the third read &amp;quot;SRR8002634.3&amp;quot;? What does this tell you about this read?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q5:&#039;&#039;&#039; Use the flags ([https://broadinstitute.github.io/picard/explain-flags.html see flags explained here]) and determine how many reads mapped to the + strand and to the - strand among the first 8 reads.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q6:&#039;&#039;&#039; Is the 10th read &amp;quot;SRR8002634.11&amp;quot; (n.b. SRR8002634.9 was removed by the trimming algorithm so we skip one) unmapped? How did you determine this? &lt;br /&gt;
&lt;br /&gt;
To get some basic statistics regarding the alignment use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools flagstat  [input.sam]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is a brief table of what the different fields mean:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| &#039;&#039;&#039;Category&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Meaning&#039;&#039;&#039;    &lt;br /&gt;
|-&lt;br /&gt;
| mapQ &lt;br /&gt;
| mapping quality&lt;br /&gt;
|- &lt;br /&gt;
| QC-passed reads&lt;br /&gt;
| most processing pipelines will QC fail reads for a variety of reasons, those are the ones that were not failed i.e. can be used for analysis&lt;br /&gt;
|-&lt;br /&gt;
| QC-failed reads&lt;br /&gt;
| as mentioned above, those are read with any kind of problem as determined by the processing pipeline and should not be used by downstream analyses. Most properly coded software will overlook those reads.&lt;br /&gt;
|-&lt;br /&gt;
| total&lt;br /&gt;
| total number of alignments&lt;br /&gt;
|- &lt;br /&gt;
| secondary&lt;br /&gt;
| if a mapper aligns a read equally well to 2 or more locations, I can report the best location as primary alignment and any other ones as secondary&lt;br /&gt;
|- &lt;br /&gt;
| supplementary&lt;br /&gt;
| If, for instance, the beginning of a read aligns well to one location and the end of the reader aligns well to a different location in a chimeric way, one read will the &amp;quot;normal&amp;quot; read and the other one will be the &amp;quot;supplementary&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| duplicates&lt;br /&gt;
| these are reads are marked as &amp;quot;duplicates&amp;quot; will cover this at the next class&lt;br /&gt;
|-&lt;br /&gt;
| mapped&lt;br /&gt;
| total number of reads for which there is at least one location i.e. they are not left unmapped.&lt;br /&gt;
|-&lt;br /&gt;
| paired in sequencing&lt;br /&gt;
| I have reads that are paired (versus single-end)&lt;br /&gt;
|-&lt;br /&gt;
| read1&lt;br /&gt;
| forward reads&lt;br /&gt;
|-&lt;br /&gt;
|read2&lt;br /&gt;
|reverse reads&lt;br /&gt;
|-&lt;br /&gt;
| properly paired&lt;br /&gt;
| we have covered this and class, meaning facing each other and within a reasonable distance. &lt;br /&gt;
|-&lt;br /&gt;
| with itself and mate mapped&lt;br /&gt;
| the read maps and also its mate (forward or reverse) but may or may not satisfy the properly paired requirement.&lt;br /&gt;
|-&lt;br /&gt;
| singletons &lt;br /&gt;
| the read was mapped but not its mate&lt;br /&gt;
|- &lt;br /&gt;
|with mate mapped to a different chr&lt;br /&gt;
| the read was mapped but its mate mapped to different chromosome&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q7:&#039;&#039;&#039; what is the fraction of reads that did not align to the reference?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Working with alignments&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;Format conversion&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This should be the first and hopefully last time you work with the SAM format. First, evaluate the size of the file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ls -lh SRR8002634_1.sam&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we will converted to binary SAM format or BAM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools view -bS [input.sam] &amp;gt; [output.bam]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And evaluate the space used by the BAM file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ls -lh SRR8002634_1.bam&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
-l says: give me the long listing ex: creation data, file size etc. -h make the file size human-readable (ex: 2.4M instead of 2469134). &lt;br /&gt;
&lt;br /&gt;
This BAM file contains exactly the same alignments as the previous file, to view it as SAM:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools view [input.bam] | less -S&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can filter for certain reads for a specific flag for example, to only include unmapped reads:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools view -f 0x4 [input.bam] &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or to exclude unmapped reads:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools view -F 0x4 [input.bam] &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Why 0x4? refer to [https://broadinstitute.github.io/picard/explain-flags.html Decoding SAM flags].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q8:&#039;&#039;&#039; what is the size ratio of SAM to BAM?&lt;br /&gt;
&lt;br /&gt;
Then we can convert it to CRAM which compresseses it even further using the reference:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools view -C -T [reference genome in fasta]  [input.bam] &amp;gt; [output.cram]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [reference genome in fasta] is exactly the same file you used for mapping.&lt;br /&gt;
&lt;br /&gt;
use &amp;quot;ls -lh&amp;quot; to find the file size.&lt;br /&gt;
&lt;br /&gt;
To view the alignment as SAM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools view -T [reference genome in fasta]  [input.cram] | less -S&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q9:&#039;&#039;&#039; what is the size ratio of BAM to CRAM?&lt;br /&gt;
&lt;br /&gt;
Please remove the SAM file and CRAM file as we will concentrate on BAM for now, remember to remove a file: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
rm [file]&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;Sorting&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First, sort the BAM file using samtools sort:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools sort  [input.bam] &amp;gt; [output.bam]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be careful not to overwrite the original file, the [input.bam] can be SRR8002634_1.bam whereas [output.bam] can be SRR8002634_1.sorted.bam. Inspect the alignments using the command &amp;quot;samtools view&amp;quot; used above and check if the reads are sorted.&lt;br /&gt;
&lt;br /&gt;
You can now index the sorted BAM file using samtools index:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools index [input.sorted.bam] &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Remember you cannot index an unsorted BAM file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;Retrieving a particular region&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once sorted and indexed, we can retrieve specific portions of the alignment, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools view  [input.sorted.bam] [region ID]:[start]-[end] &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
For instance, the &amp;quot;[region ID]:[start]-[end]&amp;quot; can be &amp;quot;NC_002516.2:1000000-1000100&amp;quot; to retrieve all reads overlapping positions between the 1,000,000th base to the 1,000,100th base. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q10:&#039;&#039;&#039; How many reads are aligned between positions 2000000 and 3000000 on the reference NC_002516.2? (tip: to count lines in a file use &amp;quot;wc -l&amp;quot; do not write the output to another file, pipe directly as such &amp;quot;samtools view [commands] |wc -l &amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q11:&#039;&#039;&#039; How many reads with mapping quality greater or equal to 30 are aligned between positions 2000000 and 3000000 on the reference NC_002516.2? (tip: use &amp;quot;samtools view&amp;quot; without any arguments to view options).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;Average coverage&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will use mosdepth to measure the average coverage (i.e. the average number of times any base in the genome is covered) for our BAM file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mosdepth [output prefix] [input.sorted.bam]  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Feel free to use whatever [output prefix], we used SRR8002634_1. Use mosdepth on your sorted bam file and see the results in [output prefix].mosdepth.summary.txt&lt;br /&gt;
&lt;br /&gt;
Does the estimate make sense?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q12:&#039;&#039;&#039; On average, how many reads cover a base in the genome? What is the maximum number of reads covering a single position?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use the following command to view the reads on a per position basis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools mpileup [input.sorted.bam] |less -S&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;The wrong reference genome?&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q13:&#039;&#039;&#039; Imagine you would inadvertently align the data to a different reference genome, say the &#039;&#039;Yersinia pestis&#039;&#039;, the bacteria responsible for the plague, a distant relative of &#039;&#039;Pseudomonas alcaligenes&#039;&#039;. Would the number of aligned reads go up or down? Why? What would happen if the bacterial species was highly related, would you align more or less reads? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;bonus&#039;&#039;&#039;: try it:&lt;br /&gt;
The &#039;&#039;Yersinia pestis&#039;&#039; genome:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/home/databases/references/Y_pestis/GCF_000222975.1_ASM22297v1_genomic.fasta &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;Pseudomonas alcaligenes&#039;&#039; genome:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/home/databases/references/P_alcaligenes/GCF_001597285.1_ASM159728v1_genomic.fasta&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H2&amp;gt;Human paired-end Illumina reads&amp;lt;/H2&amp;gt;&lt;br /&gt;
&amp;lt;H3&amp;gt;Aligning&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will align exome-seq sequences from a [https://en.wikipedia.org/wiki/Yoruba_people Yoruba] female. The raw data can be found here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/home/projects/22126_NGS/exercises/alignment/NA19201_1.fastq.gz&lt;br /&gt;
/home/projects/22126_NGS/exercises/alignment/NA19201_2.fastq.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first one is the forward, the second, the reverse. These are pre-trimmed so no need to worry about the adapters. &lt;br /&gt;
&lt;br /&gt;
Your first exercise will be to write a single command line that will:&lt;br /&gt;
# use &#039;&#039;&#039;bwa mem&#039;&#039;&#039; to align sequences and produce SAM format output&lt;br /&gt;
# transform SAM to BAM&lt;br /&gt;
# sort the bam file&lt;br /&gt;
&lt;br /&gt;
For 1), the command line has the following format:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bwa mem [reference genome in fasta] [forward fastq]  [reverse fastq]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The human reference is here:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/home/databases/references/human/GRCh38_full_analysis_set_plus_decoy_hla.fa&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; there are multiple versions of in reference genome for a given species. The version number for this particular reference is hg38 and is the latest as of writing. However, there are various different versions of the human genome ex: hg19, hg18. The coordinates will differ and you cannot assume that the sequence at a specific chromosome/coordinate will be the same with the next genome version. Be very careful to stick with the &#039;&#039;&#039;same version&#039;&#039;&#039; throughout your analyses. &lt;br /&gt;
&lt;br /&gt;
If you can, add the read groups+sample, let us say that the read group was RG26 and sample was YRB42 (tip: use -R &amp;quot;@RG\tID:RG26\tSM:YRB42&amp;quot; in bwa mem).&lt;br /&gt;
&lt;br /&gt;
This command will produce SAM on the STDOUT. Next, we want to convert SAM to BAM:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools view -bS [input SAM]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your case, the input is in SAM format and will be the STDIN: /dev/stdin. The command above will produce BAM on the STDOUT. Next, we want to sort:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools sort [input BAM]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, the input is in BAM format and will be the STDIN: /dev/stdin. The command above will produce BAM (but sorted) on the STDOUT.  The output should be redirected to a file.&lt;br /&gt;
&lt;br /&gt;
Type down the command as a single line, run it and send the output to NA19201.bam. The alignment takes about 10 minutes, so free to take a bathroom break. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q14:&#039;&#039;&#039; How to run all of the steps above on a single line using UNIX pipes?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q15:&#039;&#039;&#039; There two major advantages of using UNIX pipes over simply running each command at the time. What would those be?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;n.b.&#039;&#039;&#039; For full disclosure, the reads were only the ones that only mapped to &#039;&#039;&#039;chr20&#039;&#039;&#039;. We did this to speed things up a bit. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Statistics&amp;lt;/H3&amp;gt;&lt;br /&gt;
&amp;lt;H4&amp;gt;flagstat&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q16:&#039;&#039;&#039; Using &#039;&#039;&#039;samtools flagstat&#039;&#039;&#039;, what is the proportion of reads that aligned to the reference?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q17&#039;&#039;&#039; Using the same command, how many pairs are properly paired?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q18&#039;&#039;&#039; Index the file and use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools view  [input BAM] [chromosome name]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
And determine how many total reads aligned to &#039;&#039;&#039;chr20&#039;&#039;&#039; (reminder: use &#039;&#039;&#039;wc -l&#039;&#039;&#039; to count lines).  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;stat&amp;lt;/H4&amp;gt;&lt;br /&gt;
Use&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
samtools stat [input BAM]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
To generate additional statistics. The command above generates a bunch of statistics and produces it on the standard out (STDOUT). Redirect this to a file (ex:  NA19201.stat). We will then use &#039;&#039;&#039;plot-bamstats&#039;&#039;&#039; on the stat file that you have produced to create a congenial interface, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
plot-bamstats -p NA19201 NA19201.stat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
firefox NA19201.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q19&#039;&#039;&#039; look at the graph of the insert size, what would you say is the most common insert size? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;igv&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will now use igv (integrated genome viewer) to look at the alignment per se. First, start:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
igv &amp;amp;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will do the following to load the file:&lt;br /&gt;
# You should see a drop-down field with probably the text &amp;quot;Human hg19&amp;quot; written in it. This is your genome and genome version. Select &amp;quot; More...&amp;quot;, find and select &amp;quot;Human hg38&amp;quot; and press ok. &lt;br /&gt;
# Go to &amp;quot;File&amp;quot;, &amp;quot;load from file&amp;quot; and select your BAM file.&lt;br /&gt;
# next to the field when you&#039;ve selected your genome build, there is a possibility to select a chromosome, please select &amp;quot;chr20&amp;quot;.&lt;br /&gt;
# next to the field for the chromosome, you can zoom to a specific location, type: chr20:35,581,362&lt;br /&gt;
&lt;br /&gt;
There seems to be a variant that position, use igv to answer the following questions&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q20&#039;&#039;&#039;: what is the reference base? What is the base that seems to be in the sample?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q21&#039;&#039;&#039;: how many reads support this particular base?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q22&#039;&#039;&#039;: this mutation seems to fall in a gene, what is the name of the gene?&lt;br /&gt;
&lt;br /&gt;
Feel free to use igv to look at different loci on chromosome 20.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Please find the answers [[Alignment_exercise_answers|here]] &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Congratulations you finished the exercise!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=182</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=182"/>
		<updated>2025-01-06T14:29:22Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2024/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2024/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2024/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2024/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2024/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2024/42_post_alignment_variantcalling_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2024/Long_read_sequencing_Lecture_08-01-2023.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2024/dtu_adna_2024.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]]) &amp;lt;!-- ([[Rnaseq_exercise_answers]]) --&amp;gt; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2024/Genomic_epidemiology_NGScourse_Jan2024.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2024/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2024/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;recap test &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2024])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Astrid Brix Saksager, Grigorii Nos &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Astrid Brix Saksager, Grigorii Nos&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancerseq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=181</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=181"/>
		<updated>2025-01-06T14:26:03Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2024/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2024/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2024/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2024/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2024/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2024/42_post_alignment_variantcalling_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2024/Long_read_sequencing_Lecture_08-01-2023.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2024/dtu_adna_2024.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]])  ([[Rnaseq_exercise_answers]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2024/Genomic_epidemiology_NGScourse_Jan2024.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2024/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2024/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;recap test &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2024])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Astrid Brix Saksager, Grigorii Nos &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Astrid Brix Saksager, Grigorii Nos&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancerseq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=180</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=180"/>
		<updated>2025-01-06T14:25:37Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2024/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2024/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2024/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2024/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2024/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2024/42_post_alignment_variantcalling_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2024/Long_read_sequencing_Lecture_08-01-2023.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2024/dtu_adna_2024.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]])  ([[Rnaseq_exercise_answers]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2024/Genomic_epidemiology_NGScourse_Jan2024.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2024/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2024/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;CancerSeq &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt; Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2024])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Astrid Brix Saksager, Grigorii Nos &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-12pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to work on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Astrid Brix Saksager, Grigorii Nos&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is the cancerseq lecture from previous years if you would like to see it:&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=179</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=179"/>
		<updated>2025-01-06T14:22:24Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2024/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2024/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2024/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2024/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2024/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2024/42_post_alignment_variantcalling_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2024/Long_read_sequencing_Lecture_08-01-2023.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and RNAseq&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2024/dtu_adna_2024.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]])  ([[Rnaseq_exercise_answers]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2024/Genomic_epidemiology_NGScourse_Jan2024.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2024/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2024/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;CancerSeq &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Matteo Arnaudi, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=178</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=178"/>
		<updated>2025-01-06T14:21:55Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2024/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2024/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2024/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2024/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2024/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2024/42_post_alignment_variantcalling_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2024/Long_read_sequencing_Lecture_08-01-2023.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and recap test&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2024/dtu_adna_2024.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]])  ([[Rnaseq_exercise_answers]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2024/Genomic_epidemiology_NGScourse_Jan2024.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2024/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2024/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;CancerSeq &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Matteo Arnaudi, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=177</id>
		<title>Program 2025</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Program_2025&amp;diff=177"/>
		<updated>2025-01-06T11:16:47Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;REMEMBER TO BRING A LAPTOP FOR EXERCISES&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lectures will be in person in building [https://maps.app.goo.gl/wH5EW199wrChCmWK7 341] in auditorium 23. Offline discussions will take place on Discord (https://discord.gg/7FX35qUmGX). Please register with your &#039;&#039;&#039;full name&#039;&#039;&#039;. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
Lectures and exercises will take place on Discord (https://discord.gg/FBb2edFW). Please register with your full name. Will use Discord for online classes and collaboration with your project partners.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The course has two main parts, the first half is lectures and exercises and the last half is project work ending with the exam on &#039;&#039;&#039;Friday 24th of January 2025&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For the laptop &#039;&#039;&#039; if you have a secure laptop (e.g. work laptop from Statens Serum Institut for instance), please bring your personal laptop.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This term, we will be using Piazza for class discussion. The system is highly catered to getting you help fast and efficiently from classmates, the TA, and myself. Rather than emailing questions to the teaching staff, I encourage you to post your questions on Piazza [https://piazza.com/class/kjernxm6wre7ck here]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Course Program - January 2025 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 6&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Introduction - Next Generation Sequencing&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to course &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/11_Introduction_to_course_GR.pdf Lecture slides])&lt;br /&gt;
&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;dd&amp;gt;Introduction to NGS &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/12_Introduction_to_NGS_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-10:45am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;2nd and 3rd generation NGS Technologies &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/material/22126/2024/13_Introduction_to_NGS_technology_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Logging on to our pupil servers ([[Logging on to pupil system]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann, Gabriel Renaud  &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:30pm-2:15pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-3:30pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Introduction to UNIX (continued)&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Video lectures to watch from &amp;quot;Unix intro..&amp;quot; to &amp;quot;Touching upon...&amp;quot;]) &lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22113/index.php/Unix Exercises] possible answers [[Unix_answers|here]])&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_notes Unix Notes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
([https://teaching.healthtech.dtu.dk/22126/index.php/Unix_pipes Intro. to UNIX pipes])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;First look at data&lt;br /&gt;
([[First look exercise]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;3:30pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;If you are done, some UNIX with zip codes&lt;br /&gt;
([[Zip codes]])&lt;br /&gt;
&amp;lt;DD&amp;gt;Peter Wad Sackett, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 7&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Data pre-processing &amp;amp; Alignment&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data basics ([https://teaching.healthtech.dtu.dk/material/22126/2024/21_Data_Basics_GR.pdf Lecture slides]) ([[Data basics exercise]]) ([[Data basics exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:45am-11:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;11:00am-12:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Data pre-processing ([https://teaching.healthtech.dtu.dk/material/22126/2024/22_Data_Preprocessing_GR.pdf Lecture slides]) ([[Data Preprocess exercise]]) ([[Data Preprocess exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Alignment ([https://teaching.healthtech.dtu.dk/material/22126/2024/23_Alignment_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-2:30pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:30pm-2:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Brief reminder on probabilities and Bayesian theory ([https://teaching.healthtech.dtu.dk/material/22126/2024/24_Bayesian_reminder_GR.pdf Lecture slides]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:45pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Alignment ([[Alignment exercise]]) ([[Alignment exercise answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 8&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Variant calling &#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Functional Human Variation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, ([https://teaching.healthtech.dtu.dk/material/22126/2024/41_Functional_Human_Variation_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:30am-10:15am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Variant calling part 1 ([https://teaching.healthtech.dtu.dk/material/22126/2024/42_post_alignment_variantcalling_GR.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15am-10:30am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:30am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 1 ([[Postprocess exercise]])  ([[Postprocess_exercise_answers]]) ([[SNP calling exercise part 1]]) ([[SNP_calling_exercise_answers part 1]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: variant calling part 2 ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: variant calling part 2 ([[SNP calling exercise part 2]]) ([[SNP_calling_exercise_answers part 2]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Assembly, annotation and long read sequencing&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: de novo assembly and genomic annotations ([https://teaching.healthtech.dtu.dk/material/22126/2024/43_de_novo_assembly_course_GR.pdf Lecture slides])([http://teaching.healthtech.dtu.dk/material/22126/debruijn_handout.pdf Handout]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: de novo assembly ([[denovo exercise]]) ([[denovo solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-2:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Long read sequencing ([https://teaching.healthtech.dtu.dk/material/22126/2024/Long_read_sequencing_Lecture_08-01-2023.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Frederikke Pedersen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00am-2:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:15pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Long read technology ([[longread exercise]])([[longread_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 10&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Ancient DNA and recap test&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-10:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Ancient DNA ([https://teaching.healthtech.dtu.dk/material/22126/2024/dtu_adna_2024.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00pm-10:15pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:15pm-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Ancient DNA ([[Ancient DNA exercise]]) ([[Ancient_DNA_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Martin Sikora, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: RNAseq ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_without_solutions_v2.pdf Lecture slides]) ([https://teaching.healthtech.dtu.dk/material/22126/2024/ngs_transcriptomics_kvs_2023_with_solutions_v2.pdf Lecture slides with solutions])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: RNAseq ([[Rnaseq_exercise]])  ([[Rnaseq_exercise_answers]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Kristoffer Vitting-Seerup, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Recap Test ([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024.pdf Test 2024])([https://teaching.healthtech.dtu.dk/material/22126/2024/test_2024_withA.pdf answers])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Time to catch up on this week&#039;s exercises&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 13&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Metagenomics&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Metagenomics &amp;amp; Binning ([https://teaching.healthtech.dtu.dk/material/22126/2024/Metagenomics_binning.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:45am-10:00am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Kaiju: Taxonomic classification ([[Kaiju exercise]]) ([[Kaiju solution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Quantitative Metagenomics ([https://teaching.healthtech.dtu.dk/material/22126/2024/Quantitative_metagenomics.pdf Lecture slides])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-2:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;2:00pm-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Quantitative Metagenomics ([[QuantitativeMetagenomics]]) ([[QuantitativeMetagenomicsSolution]]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Trine Zachariasen, Cecilie Thystrup, Amanda Gammelby Qvesel&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 14&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Genomic Epidemiology and group project&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:55am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Case story: Genomic Epidemiology ([https://teaching.healthtech.dtu.dk/material/22126/2024/Genomic_epidemiology_NGScourse_Jan2024.pdf Lecture])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Pimlapas Leekitecharoenphon (Shinny)&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:55am-10:10am&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:10am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Genomic Epidemiology ([[Genomic epidemiology exercise]]) ([[Genomic epidemiology solution]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-1:45pm &amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation ([https://teaching.healthtech.dtu.dk/material/22126/2024/82_Projects_GR.pdf Lecture slides] [http://teaching.healthtech.dtu.dk/material/22126/2024/posters.tar.gz Examples from previous courses]) &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:45pm-4:00pm &amp;lt;/DT&amp;gt;  &lt;br /&gt;
&amp;lt;DD&amp;gt;Projects &amp;amp; Group formation, prepare an outline for tomorrow. please write group names in the [https://docs.google.com/document/d/11paeLyAagaIB9ytUq9ZQUaLUF8nELlt_-oxpeErFm_s/edit?usp=sharing document for 2025]&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 15&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;CancerSeq &amp;amp; Project work&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-9:45am  &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Lecture: Cancer-seq ([https://teaching.healthtech.dtu.dk/material/22126/2024/Cancer_Genomics_EP_2024.pdf Lecture slides]) &amp;lt;/DD&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Elena Papaleo &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Exercise: Cancer-seq ([[Cancerseq_exercise]]) ([[Cancerseq_exercise_answers]])&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Matteo Arnaudi, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039; &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project consulation&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann &amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 16&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project presentation&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-12:00pm&amp;lt;/DT&amp;gt; &lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;DD&amp;gt;You can go to Discord for help, we will be available.&amp;lt;/DD&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;12:00pm-1:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;&#039;&#039;Lunch Break&#039;&#039;&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-4:00pm &amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 17&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Monday, January 20&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Tuesday, January 21&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wednesday, January 22&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project work&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work&amp;lt;/DD&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;1:00pm-3:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Thursday, January 23&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Project Work &amp;amp; Produce 1 page report&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;DT&amp;gt;10:00am-12:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Q&amp;amp;A: Practical information about the exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Project work/Office hours&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Gabriel Renaud, Amanda Gammelby Qvesel, Mads Hartmann&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;BR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Friday, January 24&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&#039;&#039;Exam&#039;&#039;&lt;br /&gt;
&amp;lt;DL&amp;gt;&lt;br /&gt;
&amp;lt;DT&amp;gt;9:00am-4:00pm&amp;lt;/DT&amp;gt;&lt;br /&gt;
&amp;lt;DD&amp;gt;Written Exam&amp;lt;/DD&amp;gt;&lt;br /&gt;
&amp;lt;/DL&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Logging_on_to_pupil_system&amp;diff=176</id>
		<title>Logging on to pupil system</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Logging_on_to_pupil_system&amp;diff=176"/>
		<updated>2025-01-06T10:35:01Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H2&amp;gt;Overview&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this exercise, we will prepare our computers to log on to our servers called &amp;quot;pupilX&amp;quot;, where X is 1/2/3/4/5. These are small but reliable machines. Please read the instructions carefully.&lt;br /&gt;
&lt;br /&gt;
Please be aware: there is &#039;&#039;&#039;no&#039;&#039;&#039; backup. All of your data will be deleted when the class concludes. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;H2&amp;gt;Are you physically at DTU?&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First, make sure you are connected to the internet. If you are on campus, you do not need to do anything extra, however, if you are outside campus, you need a Virtual Private Network (VPN) which simulates that you are on campus. Please refer to https://www.inside.dtu.dk/en/medarbejder/it-og-telefoni/it-support-og-kontakt/it-systemer-og-vaerktoejer/it-systemer-ait/vpn&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H2&amp;gt;Details&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Student accounts&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;To be able to perform the exercises and project you will need an account to log in to the cloud computers. Open the&lt;br /&gt;
[https://docs.google.com/spreadsheets/d/1wdx1LjRXNiMDmUCy7GfYD5j-iDEX1q0UFSTEwxm-egA/edit?usp=sharinggoogle doc], find the student id and determine which server you need to use. This will be your server that you must use for the rest of the course.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;User ID/username&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your cloud &amp;lt;b&amp;gt;username&amp;lt;/b&amp;gt; or &#039;&#039;&#039;user ID&#039;&#039;&#039; is one entered in the &#039;&#039;&#039;username&#039;&#039;&#039; column (ex: s123456).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;Server (host)/CPU/RAM&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The names/CPU/memory of the hosts:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| &#039;&#039;&#039;Server&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Full host name&#039;&#039;&#039;    &lt;br /&gt;
| &#039;&#039;&#039;CPUs&#039;&#039;&#039;    &lt;br /&gt;
| &#039;&#039;&#039;RAM&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| pupil1&lt;br /&gt;
| pupil1.healthtech.dtu.dk&lt;br /&gt;
| 40&lt;br /&gt;
| 252G&lt;br /&gt;
|-&lt;br /&gt;
| pupil2&lt;br /&gt;
| pupil2.healthtech.dtu.dk&lt;br /&gt;
| 24&lt;br /&gt;
| 110G&lt;br /&gt;
|-&lt;br /&gt;
| pupil3&lt;br /&gt;
| pupil3.healthtech.dtu.dk&lt;br /&gt;
| 24&lt;br /&gt;
| 94G&lt;br /&gt;
|-&lt;br /&gt;
| pupil4&lt;br /&gt;
| pupil4.healthtech.dtu.dk&lt;br /&gt;
| 48&lt;br /&gt;
| 126G&lt;br /&gt;
|-&lt;br /&gt;
| pupil5&lt;br /&gt;
| pupil5.healthtech.dtu.dk&lt;br /&gt;
| 48&lt;br /&gt;
| 126G&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;Password&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The password is the &#039;&#039;&#039;same&#039;&#039;&#039; as the DTU one. &amp;lt;b&amp;gt; Remember: If you lose your DTU password we can not help you! Check with DTU.&amp;lt;/b&amp;gt; &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;H4&amp;gt;2 factor authentication&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will be prompted for a 2-factor authentication code, using the same system as for logging in to your DTU mail. Look at your phone.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
This should be set up already - according to DTU IT (AIT). If you continue to fail at logging in, it might not be set up for you on Azure.&amp;lt;br&amp;gt;&lt;br /&gt;
To do the setup yourself, go to: [https://account.activedirectory.windowsazure.com/proofup.aspx?proofup=1 https://account.activedirectory.windowsazure.com/proofup.aspx?proofup=1]. Use your DTU username/password to enroll.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Windows computer&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;Terminal&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You have 3 choices here:&lt;br /&gt;
# MobaXterm. Described [https://teaching.healthtech.dtu.dk/22113/index.php/Course_preparation#MobaXterm.2C_not_really_recommended here]. Install MobaXterm. Download [https://mobaxterm.mobatek.net/download.html here]&amp;lt;br&amp;gt;Once installed you must create an &#039;&#039;&#039;ssh session&#039;&#039;&#039; in Mobaxterm and log on to your cloud server (Look at the Google docs depending on user ID and use the IP above). Easy choice if you do not plan for more programming in the future.&lt;br /&gt;
# WSL2 + Ubuntu install. Described [https://teaching.healthtech.dtu.dk/22113/index.php/Course_preparation#WSL.2FWSL2.2C_Windows_Subsystem_for_Linux here]. Best choice if taking a course like 22113 later.&lt;br /&gt;
# PuTTY + Xming. A small terminal can be downloaded [https://www.putty.org/ here] and an X-server to be downloaded [https://sourceforge.net/projects/xming/ here].&lt;br /&gt;
The cookie-cutter solution is MobaXterm, which gives you the terminal and X-server functionality right out of the box.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Mac computer&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;Terminal&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Open your terminal. It is located in: /Applications/Utilities. Or search for &amp;quot;Terminal&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Depending on the server you will be using (see the google sheet), write:&lt;br /&gt;
&lt;br /&gt;
 ssh -XC [USER_ID]@[FULLHOSTNAME]&lt;br /&gt;
replace the [USER_ID] with the username you have been assigned to and [ID ADDRESS] is the IP of your server (see above).&lt;br /&gt;
&lt;br /&gt;
Enter the password..&lt;br /&gt;
&amp;lt;p&amp;gt;Open the &amp;quot;XQuartz&amp;quot; and &amp;quot;Terminal&amp;quot; in the &amp;quot;Applications/Utilities&amp;quot; folder. You can close the window that the XQuartz program opens, but leave the program running in the background. If you dont have XQuartz installed you can install&lt;br /&gt;
it from [https://dl.bintray.com/xquartz/downloads/XQuartz-2.7.11.dmg here].&lt;br /&gt;
In the terminal write the command below and enter your password when asked for it. Depending on what you have installed you may have to install &amp;quot;Developer Tools&amp;quot; from Apple. You can also install the program &amp;quot;iTerm2&amp;quot; which is a very neat terminal.&amp;lt;br&amp;gt; &lt;br /&gt;
Log on to your cloud server using ssh and your cloud username (studXXX) and password (see above).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;HR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;Ubuntu/Linux&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H4&amp;gt;Terminal&amp;lt;/H4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Open your terminal and ssh using:&lt;br /&gt;
 ssh -XC [USER_ID]@[FULLHOSTNAME]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt;ssh without any keys&amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Are you tired of typing your password and the 2-factor authentication code? If so you can automate the process using this on Ubuntu/Linux/MacOS:&lt;br /&gt;
 ssh-copy-id [USERID]@[FULLHOSTNAME]&lt;br /&gt;
It will seem like a normal login, which logs you out again immediately. However, in the future, you do no need to supply DTU credentials.&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=175</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=175"/>
		<updated>2024-12-17T14:04:52Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check up to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number checker . This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(2, int(math.sqrt(num))+1):&lt;br /&gt;
        if num % i == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
=== RSA Checker ===&lt;br /&gt;
&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
from sympy import mod_inverse, isprime&lt;br /&gt;
&lt;br /&gt;
def read_primes_from_file(file_path):&lt;br /&gt;
    try:&lt;br /&gt;
        with open(file_path, &#039;r&#039;) as file:&lt;br /&gt;
            values = [int(line.strip()) for line in file if line.strip().isdigit()]&lt;br /&gt;
            for value in values:&lt;br /&gt;
                if not isprime(value):&lt;br /&gt;
                    raise ValueError(f&amp;quot;The number {value} in {file_path} is not a prime number.&amp;quot;)&lt;br /&gt;
            return values&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Error reading primes from file {file_path}: {e}&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
def generate_rsa_keys(p, q):&lt;br /&gt;
    if p == q:&lt;br /&gt;
        raise ValueError(&amp;quot;The two primes must be distinct.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate n and phi(n)&lt;br /&gt;
    n = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    # Choose an encryption exponent e&lt;br /&gt;
    e = 65537  # Commonly used value for e&lt;br /&gt;
    if e &amp;gt;= phi_n or gcd(e, phi_n) != 1:&lt;br /&gt;
        raise ValueError(&amp;quot;Invalid value for e. It must be coprime with phi(n) and less than phi(n).&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate the decryption exponent d&lt;br /&gt;
    d = mod_inverse(e, phi_n)&lt;br /&gt;
&lt;br /&gt;
    return (e, n), (d, n)&lt;br /&gt;
&lt;br /&gt;
def gcd(a, b):&lt;br /&gt;
    while b:&lt;br /&gt;
        a, b = b, a % b&lt;br /&gt;
    return a&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python rsa_key_gen.py &amp;lt;prime_file_1&amp;gt; &amp;lt;prime_file_2&amp;gt;&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    prime_file_1 = sys.argv[1]&lt;br /&gt;
    prime_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Read primes from files&lt;br /&gt;
    primes1 = read_primes_from_file(prime_file_1)&lt;br /&gt;
    primes2 = read_primes_from_file(prime_file_2)&lt;br /&gt;
&lt;br /&gt;
    # Take the minimum length of the two prime lists&lt;br /&gt;
    min_length = min(len(primes1), len(primes2))&lt;br /&gt;
    primes1 = primes1[:min_length]&lt;br /&gt;
    primes2 = primes2[:min_length]&lt;br /&gt;
&lt;br /&gt;
    # Generate RSA keys for each pair of primes&lt;br /&gt;
    for p, q in zip(primes1, primes2):&lt;br /&gt;
        try:&lt;br /&gt;
            public_key, private_key = generate_rsa_keys(p, q)&lt;br /&gt;
            # Print keys to stdout&lt;br /&gt;
            print(f&amp;quot;Public Key: {public_key[0]}\t{public_key[1]}\tPrivate Key: {private_key[0]}\t{private_key[1]}&amp;quot;)&lt;br /&gt;
        except ValueError as e:&lt;br /&gt;
            print(f&amp;quot;Error generating keys for primes {p} and {q}: {e}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This Python program demonstrates RSA key generation using prime numbers read from two input files. It pairs each prime number from the first file with one from the second file, generates public and private keys for each pair, and prints them to the console. RSA is a widely used encryption scheme using prime numbers.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
&lt;br /&gt;
  python /home/projects/22126_NGS/exercises/pipes/RSAcompute.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
  python3 /home/projects/22126_NGS/exercises/pipes/RSAcompute.py &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py --min 1000000 --max 10000000 10000 | python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py) &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py --min 1000000 --max 10000000 10000| python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py)&lt;br /&gt;
&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need 2 files of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAcompute.py`. &amp;quot;&amp;lt;( PROCESS HERE )&amp;quot; will take the stdout of PROCESS HERE and turn it into a file descriptor. Essentially, we have saved writing 4 files here using file descriptors and, RSAcompute.py goes as fast as random_int_generator and prime_checker can go. &lt;br /&gt;
&lt;br /&gt;
It worked perfectly, and we have RSA pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Benchmarking ==&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
=== Time Efficiency Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
&#039;Random Integer Generator and Prime Checker&#039;&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
&#039;Using Intermediate Files&#039;&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
 time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
 time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which makes a total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
&#039;Using Pipes&#039;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=174</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=174"/>
		<updated>2024-12-16T21:58:42Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check up to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number checker . This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(2, int(math.sqrt(num))+1):&lt;br /&gt;
        if num % i == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
=== RSA Checker ===&lt;br /&gt;
&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
from sympy import mod_inverse, isprime&lt;br /&gt;
&lt;br /&gt;
def read_primes_from_file(file_path):&lt;br /&gt;
    try:&lt;br /&gt;
        with open(file_path, &#039;r&#039;) as file:&lt;br /&gt;
            values = [int(line.strip()) for line in file if line.strip().isdigit()]&lt;br /&gt;
            for value in values:&lt;br /&gt;
                if not isprime(value):&lt;br /&gt;
                    raise ValueError(f&amp;quot;The number {value} in {file_path} is not a prime number.&amp;quot;)&lt;br /&gt;
            return values&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Error reading primes from file {file_path}: {e}&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
def generate_rsa_keys(p, q):&lt;br /&gt;
    if p == q:&lt;br /&gt;
        raise ValueError(&amp;quot;The two primes must be distinct.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate n and phi(n)&lt;br /&gt;
    n = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    # Choose an encryption exponent e&lt;br /&gt;
    e = 65537  # Commonly used value for e&lt;br /&gt;
    if e &amp;gt;= phi_n or gcd(e, phi_n) != 1:&lt;br /&gt;
        raise ValueError(&amp;quot;Invalid value for e. It must be coprime with phi(n) and less than phi(n).&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate the decryption exponent d&lt;br /&gt;
    d = mod_inverse(e, phi_n)&lt;br /&gt;
&lt;br /&gt;
    return (e, n), (d, n)&lt;br /&gt;
&lt;br /&gt;
def gcd(a, b):&lt;br /&gt;
    while b:&lt;br /&gt;
        a, b = b, a % b&lt;br /&gt;
    return a&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python rsa_key_gen.py &amp;lt;prime_file_1&amp;gt; &amp;lt;prime_file_2&amp;gt;&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    prime_file_1 = sys.argv[1]&lt;br /&gt;
    prime_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Read primes from files&lt;br /&gt;
    primes1 = read_primes_from_file(prime_file_1)&lt;br /&gt;
    primes2 = read_primes_from_file(prime_file_2)&lt;br /&gt;
&lt;br /&gt;
    # Take the minimum length of the two prime lists&lt;br /&gt;
    min_length = min(len(primes1), len(primes2))&lt;br /&gt;
    primes1 = primes1[:min_length]&lt;br /&gt;
    primes2 = primes2[:min_length]&lt;br /&gt;
&lt;br /&gt;
    # Generate RSA keys for each pair of primes&lt;br /&gt;
    for p, q in zip(primes1, primes2):&lt;br /&gt;
        try:&lt;br /&gt;
            public_key, private_key = generate_rsa_keys(p, q)&lt;br /&gt;
            # Print keys to stdout&lt;br /&gt;
            print(f&amp;quot;Public Key: {public_key[0]}\t{public_key[1]}\tPrivate Key: {private_key[0]}\t{private_key[1]}&amp;quot;)&lt;br /&gt;
        except ValueError as e:&lt;br /&gt;
            print(f&amp;quot;Error generating keys for primes {p} and {q}: {e}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This Python program demonstrates RSA key generation using prime numbers read from two input files. It pairs each prime number from the first file with one from the second file, generates public and private keys for each pair, and prints them to the console. RSA is a widely used encryption scheme using prime numbers.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
&lt;br /&gt;
  python /home/projects/22126_NGS/exercises/pipes/RSAcompute.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
  python3 /home/projects/22126_NGS/exercises/pipes/RSAcompute.py &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py --min 1000000 --max 10000000 10000 | python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py) &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py --min 1000000 --max 10000000 10000| python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py)&lt;br /&gt;
&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need 2 files of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAcompute.py`. &amp;quot;&amp;lt;( PROCESS HERE )&amp;quot; will take the stdout of PROCESS HERE and turn it into a file descriptor. Essentially, we have saved writing 4 files here using file descriptors and, RSAcompute.py goes as fast as random_int_generator and prime_checker can go. &lt;br /&gt;
&lt;br /&gt;
It worked perfectly, and we have RSA pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Benchmarking ==&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
=== Time Efficiency Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
&#039;Random Integer Generator and Prime Checker&#039;&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
&#039;Using Intermediate Files&#039;&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
 time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
 time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
&#039;Using Pipes&#039;&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=173</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=173"/>
		<updated>2024-12-16T21:56:36Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* RSA Checker */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check up to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number checker . This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(2, int(math.sqrt(num))+1):&lt;br /&gt;
        if num % i == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
=== RSA Checker ===&lt;br /&gt;
&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
from sympy import mod_inverse, isprime&lt;br /&gt;
&lt;br /&gt;
def read_primes_from_file(file_path):&lt;br /&gt;
    try:&lt;br /&gt;
        with open(file_path, &#039;r&#039;) as file:&lt;br /&gt;
            values = [int(line.strip()) for line in file if line.strip().isdigit()]&lt;br /&gt;
            for value in values:&lt;br /&gt;
                if not isprime(value):&lt;br /&gt;
                    raise ValueError(f&amp;quot;The number {value} in {file_path} is not a prime number.&amp;quot;)&lt;br /&gt;
            return values&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Error reading primes from file {file_path}: {e}&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
def generate_rsa_keys(p, q):&lt;br /&gt;
    if p == q:&lt;br /&gt;
        raise ValueError(&amp;quot;The two primes must be distinct.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate n and phi(n)&lt;br /&gt;
    n = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    # Choose an encryption exponent e&lt;br /&gt;
    e = 65537  # Commonly used value for e&lt;br /&gt;
    if e &amp;gt;= phi_n or gcd(e, phi_n) != 1:&lt;br /&gt;
        raise ValueError(&amp;quot;Invalid value for e. It must be coprime with phi(n) and less than phi(n).&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate the decryption exponent d&lt;br /&gt;
    d = mod_inverse(e, phi_n)&lt;br /&gt;
&lt;br /&gt;
    return (e, n), (d, n)&lt;br /&gt;
&lt;br /&gt;
def gcd(a, b):&lt;br /&gt;
    while b:&lt;br /&gt;
        a, b = b, a % b&lt;br /&gt;
    return a&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python rsa_key_gen.py &amp;lt;prime_file_1&amp;gt; &amp;lt;prime_file_2&amp;gt;&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    prime_file_1 = sys.argv[1]&lt;br /&gt;
    prime_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Read primes from files&lt;br /&gt;
    primes1 = read_primes_from_file(prime_file_1)&lt;br /&gt;
    primes2 = read_primes_from_file(prime_file_2)&lt;br /&gt;
&lt;br /&gt;
    # Take the minimum length of the two prime lists&lt;br /&gt;
    min_length = min(len(primes1), len(primes2))&lt;br /&gt;
    primes1 = primes1[:min_length]&lt;br /&gt;
    primes2 = primes2[:min_length]&lt;br /&gt;
&lt;br /&gt;
    # Generate RSA keys for each pair of primes&lt;br /&gt;
    for p, q in zip(primes1, primes2):&lt;br /&gt;
        try:&lt;br /&gt;
            public_key, private_key = generate_rsa_keys(p, q)&lt;br /&gt;
            # Print keys to stdout&lt;br /&gt;
            print(f&amp;quot;Public Key: {public_key[0]}\t{public_key[1]}\tPrivate Key: {private_key[0]}\t{private_key[1]}&amp;quot;)&lt;br /&gt;
        except ValueError as e:&lt;br /&gt;
            print(f&amp;quot;Error generating keys for primes {p} and {q}: {e}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This Python program demonstrates RSA key generation using prime numbers read from two input files. It pairs each prime number from the first file with one from the second file, generates public and private keys for each pair, and prints them to the console. RSA is a widely used encryption scheme using prime numbers.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
&lt;br /&gt;
  python /home/projects/22126_NGS/exercises/pipes/RSAcompute.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
  python3 /home/projects/22126_NGS/exercises/pipes/RSAcompute.py &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py --min 1000000 --max 10000000 10000 | python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py) &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py --min 1000000 --max 10000000 10000| python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py)&lt;br /&gt;
&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need 2 files of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAcompute.py`. &amp;quot;&amp;lt;( PROCESS HERE )&amp;quot; will take the stdout of PROCESS HERE and turn it into a file descriptor. Essentially, we have saved writing 4 files here using file descriptors and, RSAcompute.py goes as fast as random_int_generator and prime_checker can go. &lt;br /&gt;
&lt;br /&gt;
It worked perfectly, and we have RSA pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Benchmarking ==&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
=== Time Efficiency Benchmarking ===&lt;br /&gt;
&lt;br /&gt;
&#039;Random Integer Generator and Prime Checker&#039;&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
&#039;Using Intermediate Files&#039;&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
 time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
 time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=172</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=172"/>
		<updated>2024-12-16T21:51:35Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* RSA Checker */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check up to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number checker . This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(2, int(math.sqrt(num))+1):&lt;br /&gt;
        if num % i == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
=== RSA Checker ===&lt;br /&gt;
&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
from sympy import mod_inverse, isprime&lt;br /&gt;
&lt;br /&gt;
def read_primes_from_file(file_path):&lt;br /&gt;
    try:&lt;br /&gt;
        with open(file_path, &#039;r&#039;) as file:&lt;br /&gt;
            values = [int(line.strip()) for line in file if line.strip().isdigit()]&lt;br /&gt;
            for value in values:&lt;br /&gt;
                if not isprime(value):&lt;br /&gt;
                    raise ValueError(f&amp;quot;The number {value} in {file_path} is not a prime number.&amp;quot;)&lt;br /&gt;
            return values&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Error reading primes from file {file_path}: {e}&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
def generate_rsa_keys(p, q):&lt;br /&gt;
    if p == q:&lt;br /&gt;
        raise ValueError(&amp;quot;The two primes must be distinct.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate n and phi(n)&lt;br /&gt;
    n = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    # Choose an encryption exponent e&lt;br /&gt;
    e = 65537  # Commonly used value for e&lt;br /&gt;
    if e &amp;gt;= phi_n or gcd(e, phi_n) != 1:&lt;br /&gt;
        raise ValueError(&amp;quot;Invalid value for e. It must be coprime with phi(n) and less than phi(n).&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate the decryption exponent d&lt;br /&gt;
    d = mod_inverse(e, phi_n)&lt;br /&gt;
&lt;br /&gt;
    return (e, n), (d, n)&lt;br /&gt;
&lt;br /&gt;
def gcd(a, b):&lt;br /&gt;
    while b:&lt;br /&gt;
        a, b = b, a % b&lt;br /&gt;
    return a&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python rsa_key_gen.py &amp;lt;prime_file_1&amp;gt; &amp;lt;prime_file_2&amp;gt;&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    prime_file_1 = sys.argv[1]&lt;br /&gt;
    prime_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Read primes from files&lt;br /&gt;
    primes1 = read_primes_from_file(prime_file_1)&lt;br /&gt;
    primes2 = read_primes_from_file(prime_file_2)&lt;br /&gt;
&lt;br /&gt;
    # Take the minimum length of the two prime lists&lt;br /&gt;
    min_length = min(len(primes1), len(primes2))&lt;br /&gt;
    primes1 = primes1[:min_length]&lt;br /&gt;
    primes2 = primes2[:min_length]&lt;br /&gt;
&lt;br /&gt;
    # Generate RSA keys for each pair of primes&lt;br /&gt;
    for p, q in zip(primes1, primes2):&lt;br /&gt;
        try:&lt;br /&gt;
            public_key, private_key = generate_rsa_keys(p, q)&lt;br /&gt;
            # Print keys to stdout&lt;br /&gt;
            print(f&amp;quot;Public Key: {public_key[0]}\t{public_key[1]}\tPrivate Key: {private_key[0]}\t{private_key[1]}&amp;quot;)&lt;br /&gt;
        except ValueError as e:&lt;br /&gt;
            print(f&amp;quot;Error generating keys for primes {p} and {q}: {e}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This Python program demonstrates RSA key generation using prime numbers read from two input files. It pairs each prime number from the first file with one from the second file, generates public and private keys for each pair, and prints them to the console. RSA is a widely used encryption scheme using prime numbers.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
&lt;br /&gt;
  python /home/projects/22126_NGS/exercises/pipes/RSAcompute.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/RSAcompute.py &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_integer_generator.py | python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py) &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_integer_generator.py | python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py)&lt;br /&gt;
&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=171</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=171"/>
		<updated>2024-12-16T21:49:02Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* RSA Checker */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check up to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number checker . This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(2, int(math.sqrt(num))+1):&lt;br /&gt;
        if num % i == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
=== RSA Checker ===&lt;br /&gt;
&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
from sympy import mod_inverse, isprime&lt;br /&gt;
&lt;br /&gt;
def read_primes_from_file(file_path):&lt;br /&gt;
    try:&lt;br /&gt;
        with open(file_path, &#039;r&#039;) as file:&lt;br /&gt;
            values = [int(line.strip()) for line in file if line.strip().isdigit()]&lt;br /&gt;
            for value in values:&lt;br /&gt;
                if not isprime(value):&lt;br /&gt;
                    raise ValueError(f&amp;quot;The number {value} in {file_path} is not a prime number.&amp;quot;)&lt;br /&gt;
            return values&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Error reading primes from file {file_path}: {e}&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
def generate_rsa_keys(p, q):&lt;br /&gt;
    if p == q:&lt;br /&gt;
        raise ValueError(&amp;quot;The two primes must be distinct.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate n and phi(n)&lt;br /&gt;
    n = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    # Choose an encryption exponent e&lt;br /&gt;
    e = 65537  # Commonly used value for e&lt;br /&gt;
    if e &amp;gt;= phi_n or gcd(e, phi_n) != 1:&lt;br /&gt;
        raise ValueError(&amp;quot;Invalid value for e. It must be coprime with phi(n) and less than phi(n).&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate the decryption exponent d&lt;br /&gt;
    d = mod_inverse(e, phi_n)&lt;br /&gt;
&lt;br /&gt;
    return (e, n), (d, n)&lt;br /&gt;
&lt;br /&gt;
def gcd(a, b):&lt;br /&gt;
    while b:&lt;br /&gt;
        a, b = b, a % b&lt;br /&gt;
    return a&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python rsa_key_gen.py &amp;lt;prime_file_1&amp;gt; &amp;lt;prime_file_2&amp;gt;&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    prime_file_1 = sys.argv[1]&lt;br /&gt;
    prime_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Read primes from files&lt;br /&gt;
    primes1 = read_primes_from_file(prime_file_1)&lt;br /&gt;
    primes2 = read_primes_from_file(prime_file_2)&lt;br /&gt;
&lt;br /&gt;
    # Take the minimum length of the two prime lists&lt;br /&gt;
    min_length = min(len(primes1), len(primes2))&lt;br /&gt;
    primes1 = primes1[:min_length]&lt;br /&gt;
    primes2 = primes2[:min_length]&lt;br /&gt;
&lt;br /&gt;
    # Generate RSA keys for each pair of primes&lt;br /&gt;
    for p, q in zip(primes1, primes2):&lt;br /&gt;
        try:&lt;br /&gt;
            public_key, private_key = generate_rsa_keys(p, q)&lt;br /&gt;
            # Print keys to stdout&lt;br /&gt;
            print(f&amp;quot;Public Key: {public_key[0]}\n{public_key[1]}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Private Key: {private_key[0]}\n{private_key[1]}&amp;quot;)&lt;br /&gt;
        except ValueError as e:&lt;br /&gt;
            print(f&amp;quot;Error generating keys for primes {p} and {q}: {e}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This Python program demonstrates RSA key generation using prime numbers read from two input files. It pairs each prime number from the first file with one from the second file, generates public and private keys for each pair, and prints them to the console. RSA is a widely used encryption scheme using prime numbers.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
&lt;br /&gt;
  python /home/projects/22126_NGS/exercises/pipes/RSAcompute.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/RSAcompute.py &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_integer_generator.py | python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py) &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_integer_generator.py | python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py)&lt;br /&gt;
&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=170</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=170"/>
		<updated>2024-12-16T21:42:31Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* RSA Checker */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check up to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number checker . This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(2, int(math.sqrt(num))+1):&lt;br /&gt;
        if num % i == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
=== RSA Checker ===&lt;br /&gt;
&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
from sympy import mod_inverse, isprime&lt;br /&gt;
&lt;br /&gt;
def read_primes_from_file(file_path):&lt;br /&gt;
    try:&lt;br /&gt;
        with open(file_path, &#039;r&#039;) as file:&lt;br /&gt;
            values = [int(line.strip()) for line in file if line.strip().isdigit()]&lt;br /&gt;
            for value in values:&lt;br /&gt;
                if not isprime(value):&lt;br /&gt;
                    raise ValueError(f&amp;quot;The number {value} in {file_path} is not a prime number.&amp;quot;)&lt;br /&gt;
            return values&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print(f&amp;quot;Error reading primes from file {file_path}: {e}&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
def generate_rsa_keys(p, q):&lt;br /&gt;
    if p == q:&lt;br /&gt;
        raise ValueError(&amp;quot;The two primes must be distinct.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate n and phi(n)&lt;br /&gt;
    n = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    # Choose an encryption exponent e&lt;br /&gt;
    e = 65537  # Commonly used value for e&lt;br /&gt;
    if e &amp;gt;= phi_n or gcd(e, phi_n) != 1:&lt;br /&gt;
        raise ValueError(&amp;quot;Invalid value for e. It must be coprime with phi(n) and less than phi(n).&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # Calculate the decryption exponent d&lt;br /&gt;
    d = mod_inverse(e, phi_n)&lt;br /&gt;
&lt;br /&gt;
    return (e, n), (d, n)&lt;br /&gt;
&lt;br /&gt;
def gcd(a, b):&lt;br /&gt;
    while b:&lt;br /&gt;
        a, b = b, a % b&lt;br /&gt;
    return a&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python rsa_key_gen.py &amp;lt;prime_file_1&amp;gt; &amp;lt;prime_file_2&amp;gt;&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    prime_file_1 = sys.argv[1]&lt;br /&gt;
    prime_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Read primes from files&lt;br /&gt;
    primes1 = read_primes_from_file(prime_file_1)&lt;br /&gt;
    primes2 = read_primes_from_file(prime_file_2)&lt;br /&gt;
&lt;br /&gt;
    if len(primes1) != len(primes2):&lt;br /&gt;
        print(&amp;quot;Error: Both files must contain the same number of primes.&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    # Generate RSA keys for each pair of primes&lt;br /&gt;
    for p, q in zip(primes1, primes2):&lt;br /&gt;
        try:&lt;br /&gt;
            public_key, private_key = generate_rsa_keys(p, q)&lt;br /&gt;
            # Print keys to stdout&lt;br /&gt;
            print(f&amp;quot;Public Keys: {public_key[0]}\t{public_key[1]}\tPrivate Keys: {private_key[0]}\t{private_key[1]}&amp;quot;)&lt;br /&gt;
        except ValueError as e:&lt;br /&gt;
            print(f&amp;quot;Error generating keys for primes {p} and {q}: {e}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This Python program demonstrates RSA key generation using prime numbers read from two input files. It pairs each prime number from the first file with one from the second file, generates public and private keys for each pair, and prints them to the console. RSA is a widely used encryption scheme using prime numbers.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
&lt;br /&gt;
  python /home/projects/22126_NGS/exercises/pipes/RSAcompute.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/RSAcompute.py &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_integer_generator.py | python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py) &amp;lt;(python3 /home/projects/22126_NGS/exercises/pipes/random_integer_generator.py | python3 /home/projects/22126_NGS/exercises/pipes/prime_checker.py)&lt;br /&gt;
&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=169</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=169"/>
		<updated>2024-12-16T21:38:29Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* Prime Checker (Naive) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check up to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number checker . This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(2, int(math.sqrt(num))+1):&lt;br /&gt;
        if num % i == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
=== RSA Checker ===&lt;br /&gt;
&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to check RSA key pairs from two lists of prime numbers. An RSA key pair consists of a public key and a private key. These key pairs are fundamental to the RSA encryption algorithm, which is widely used in secure communications. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
The script reads prime numbers from two files, computes the validity of the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. &lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
&lt;br /&gt;
  python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=168</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=168"/>
		<updated>2024-12-16T21:36:43Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* RSA Checker */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check up to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number checker . This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(2, num):&lt;br /&gt;
        if num % i == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
=== RSA Checker ===&lt;br /&gt;
&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to check RSA key pairs from two lists of prime numbers. An RSA key pair consists of a public key and a private key. These key pairs are fundamental to the RSA encryption algorithm, which is widely used in secure communications. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
The script reads prime numbers from two files, computes the validity of the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. &lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
&lt;br /&gt;
  python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=167</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=167"/>
		<updated>2024-12-16T15:42:06Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* Prime Checker (Naive) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check up to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number checker . This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(2, num):&lt;br /&gt;
        if num % i == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
=== RSA Checker ===&lt;br /&gt;
&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
&lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=166</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=166"/>
		<updated>2024-12-16T15:41:03Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* Prime Checker (Naive) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check up to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number checker . This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(2, num):&lt;br /&gt;
        if num % i == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=165</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=165"/>
		<updated>2024-12-16T15:40:05Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* Random Integer Generator */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check all the way to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker for Internship Task. This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(5, int(math.sqrt(num)) + 1, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=164</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=164"/>
		<updated>2024-12-16T15:38:05Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Random Integer Generator for Internship Task. This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;num_of_nums&amp;quot;, metavar=&amp;quot;n&amp;quot;, type=int, nargs=&amp;quot;?&amp;quot;, default=100, help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--min&amp;quot;, metavar=&amp;quot;min&amp;quot;, type=int, default=10, help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&amp;quot;--max&amp;quot;, metavar=&amp;quot;max&amp;quot;, type=int, default=100, help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num)&lt;br /&gt;
&lt;br /&gt;
# Run the random integer generator&lt;br /&gt;
random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
usage: random_int_generator.py [-h] [--min min] [--max max] [n]&lt;br /&gt;
&lt;br /&gt;
Random Integer Generator for Internship Task. This program generates random integers within a given interval.&lt;br /&gt;
&lt;br /&gt;
positional arguments:&lt;br /&gt;
  n           number of generated numbers (default: 100)&lt;br /&gt;
&lt;br /&gt;
optional arguments:&lt;br /&gt;
  -h, --help  show this help message and exit&lt;br /&gt;
  --min min   minimum value of the interval (default: 10)&lt;br /&gt;
  --max max   maximum value of the interval (default: 100)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values.  This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Prime Checker (Naive) ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A number is prime if it can be divided by 1 and itself. 19 and 17 are prime but not 14 (divide by 2,7) nor 16 (divided by 2,4,8). The most naive way to check if a number is prime is to check every number between 1 and the number to see if it can be divided. A slightly smarter way is to check all the way to the square root of the number. &lt;br /&gt;
 &lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import itertools&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker for Internship Task. This program checks if the input numbers are prime and writes the primes to stdout.&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    for i in range(5, int(math.sqrt(num)) + 1, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers from stdin are prime and write them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    input_data = sys.stdin.read().strip().split()&lt;br /&gt;
    numbers = map(int, input_data)&lt;br /&gt;
    &lt;br /&gt;
    primes = filter(is_prime, numbers)&lt;br /&gt;
    print(&amp;quot;\n&amp;quot;.join(map(str, primes)))&lt;br /&gt;
&lt;br /&gt;
# Run the prime checker&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    prime_checker()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime.  It outputs the prime numbers to the standard output. It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=163</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=163"/>
		<updated>2024-12-16T15:23:00Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* Real World Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
=== Random Integer Generator ===&lt;br /&gt;
&lt;br /&gt;
Let us generate random integers. Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
into this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
done! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This script is located here:&lt;br /&gt;
&lt;br /&gt;
 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py&lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 /home/projects/22126_NGS/exercises/pipes/random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=162</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=162"/>
		<updated>2024-12-16T15:17:21Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* stderr (Standard Error) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the &amp;quot;status message&amp;quot; is still going to stdout along with the output. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the redirection, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now, we want to redirect this status message into a file named `status.txt`. As we do it before, we can use redirection Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;` But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly to redirect, simply use &amp;quot;&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
== Real World Example ==&lt;br /&gt;
&lt;br /&gt;
This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=161</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=161"/>
		<updated>2024-12-16T15:13:57Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* stderr (Standard Error) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with the print function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the `status message` is still going to `stdout`. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the file descriptor, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now we want to redirect this status message into a file named `status.txt`. As we do it before, we can use `file descriptors`! Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;`! But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with following command:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
# Real World Example&lt;br /&gt;
&lt;br /&gt;
Welcome! This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=160</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=160"/>
		<updated>2024-12-16T15:11:54Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* stdin (Standard Input) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using rediction, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file. &lt;br /&gt;
&lt;br /&gt;
What happens behind the scenes? The command &amp;quot;python3 random_name_generator.py&amp;quot; writes to a special file called a file descriptor. Then &amp;quot;python3 random_name_generator.py&amp;quot; reads from that file descriptor. It is almost like the first case except:&lt;br /&gt;
# the intermediate file is deleted for you&lt;br /&gt;
# &#039;the second program does not need for the first one to finish to start executing&#039; &lt;br /&gt;
&lt;br /&gt;
The second aspect is particularly appealing for next-generation sequencing analysis.&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with print function like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the `status message` is still going to `stdout`. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the file descriptor, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now we want to redirect this status message into a file named `status.txt`. As we do it before, we can use `file descriptors`! Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;`! But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with following command:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
# Real World Example&lt;br /&gt;
&lt;br /&gt;
Welcome! This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=159</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=159"/>
		<updated>2024-12-16T15:07:40Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* stdout (Standard Output) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly the redirection of stdout. Redirection is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and redirection, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic redirection in Linux. Using it like that, you will redirect the `output` of the program into a file &amp;quot;greetings.txt&amp;quot; which will get created automatically. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== /dev/null ===&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using redirection. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using file descriptors, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with print function like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the `status message` is still going to `stdout`. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the file descriptor, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now we want to redirect this status message into a file named `status.txt`. As we do it before, we can use `file descriptors`! Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;`! But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with following command:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
# Real World Example&lt;br /&gt;
&lt;br /&gt;
Welcome! This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=158</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=158"/>
		<updated>2024-12-16T15:05:02Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* stdin (Standard Input) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly `file descriptors` of Linux. Using file descriptors is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and file descriptors, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic `file descriptors` in Linux. Using it like that, you will redirect the `output` of the program into a file. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using file descriptors. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using file descriptors, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using redirection like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a file called names.txt. But you can achieve the given task using pipes &amp;quot;|&amp;quot; like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to redirecting to an intermediate file.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== stderr (Standard Error) ===&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with print function like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the `status message` is still going to `stdout`. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the file descriptor, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now we want to redirect this status message into a file named `status.txt`. As we do it before, we can use `file descriptors`! Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;`! But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with following command:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
# Real World Example&lt;br /&gt;
&lt;br /&gt;
Welcome! This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=157</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=157"/>
		<updated>2024-12-16T15:02:02Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* stdin (Standard Input) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly `file descriptors` of Linux. Using file descriptors is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and file descriptors, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic `file descriptors` in Linux. Using it like that, you will redirect the `output` of the program into a file. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using file descriptors. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using file descriptors, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using pipes like this:&lt;br /&gt;
&lt;br /&gt;
 python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
&lt;br /&gt;
or with file descriptors:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
 python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to file descriptors.&lt;br /&gt;
&lt;br /&gt;
## stderr (Standard Error)&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with print function like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the `status message` is still going to `stdout`. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the file descriptor, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now we want to redirect this status message into a file named `status.txt`. As we do it before, we can use `file descriptors`! Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;`! But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with following command:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
# Real World Example&lt;br /&gt;
&lt;br /&gt;
Welcome! This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=156</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=156"/>
		<updated>2024-12-16T14:58:52Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* stdout (Standard Output) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can copy-paste this code block into a file using emacs, a powerful text editor (nw stands for no window to avoid a pop up window):&lt;br /&gt;
&lt;br /&gt;
 emacs -nw hello_world.py&lt;br /&gt;
&lt;br /&gt;
then press and hold CTLR followed by &#039;x&#039; and &#039;s&#039; on your keyboard. Release CTRL. This will save it. Then press and hold CTLR followed by &#039;x&#039; and &#039;c&#039; on your keyboard to quit. &lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
close(file)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly `file descriptors` of Linux. Using file descriptors is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and file descriptors, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic `file descriptors` in Linux. Using it like that, you will redirect the `output` of the program into a file. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using file descriptors. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
 import argparse&lt;br /&gt;
&lt;br /&gt;
 def main():&lt;br /&gt;
     parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
     parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
     args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
     print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
     main()&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using file descriptors, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using pipes like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
or with file descriptors:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to file descriptors.&lt;br /&gt;
&lt;br /&gt;
## stderr (Standard Error)&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with print function like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the `status message` is still going to `stdout`. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the file descriptor, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now we want to redirect this status message into a file named `status.txt`. As we do it before, we can use `file descriptors`! Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;`! But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with following command:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
# Real World Example&lt;br /&gt;
&lt;br /&gt;
Welcome! This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=155</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=155"/>
		<updated>2024-12-16T14:50:31Z</updated>

		<summary type="html">&lt;p&gt;Gabre: /* stdout (Standard Output) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/python3&lt;br /&gt;
 import sys&lt;br /&gt;
&lt;br /&gt;
 # Redirect stdout to a file&lt;br /&gt;
 with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
     sys.stdout = file&lt;br /&gt;
     print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
 close(file)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works but seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly `file descriptors` of Linux. Using file descriptors is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and file descriptors, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic `file descriptors` in Linux. Using it like that, you will redirect the `output` of the program into a file. In detail, we will talk about it in the next chapters.&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to discard the output of the program. You can do this again using file descriptors. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
&lt;br /&gt;
=== stdin (Standard Input) ===&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
But it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
 #!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
 import argparse&lt;br /&gt;
&lt;br /&gt;
 def main():&lt;br /&gt;
     parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
     parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
     args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
     print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
 if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
     main()&lt;br /&gt;
&lt;br /&gt;
That is a substantial modification. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 python3 hello_world.py rasmus&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 Hello World! rasmus&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little program). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using file descriptors, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
#!/usr/bin/python3&lt;br /&gt;
&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using pipes like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
or with file descriptors:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to file descriptors.&lt;br /&gt;
&lt;br /&gt;
## stderr (Standard Error)&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with print function like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the `status message` is still going to `stdout`. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the file descriptor, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now we want to redirect this status message into a file named `status.txt`. As we do it before, we can use `file descriptors`! Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;`! But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with following command:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
# Real World Example&lt;br /&gt;
&lt;br /&gt;
Welcome! This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=154</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=154"/>
		<updated>2024-12-16T14:37:40Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
* `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
* `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
=== mkdir (Creating Directories) ===&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing. You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir [directory_name_here]&lt;br /&gt;
&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
 mkdir my_new_directory&lt;br /&gt;
&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
 my_new_directory&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v` The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 mkdir -v my_new_directory&lt;br /&gt;
&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
=== htop ===&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
 htop&lt;br /&gt;
&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
`htop` also accepts the mouse. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
=== time ===&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
 real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
 user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
 sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== stdout, stdin and stderr ==&lt;br /&gt;
&lt;br /&gt;
=== stdout (Standard Output) ===&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
Cool, right? But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works for us, it kinda seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly `file descriptors` of Linux. Using file descriptors is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and file descriptors, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic `file descriptors` in Linux. Using it like that, you will redirect the `output` of the program into a file. In detail, we will talk about it in next chapters.&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to delete the output of the program. You can do this again using file descriptors. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
## stdin (Standard Input)&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, &amp;quot;legally&amp;quot;, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py ozgur&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Aaaaand it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Well, that&#039;s a huge modification at all. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py ozgur&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! ozgur&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little programme). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using file descriptors, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using pipes like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
or with file descriptors:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to file descriptors.&lt;br /&gt;
&lt;br /&gt;
## stderr (Standard Error)&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with print function like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the `status message` is still going to `stdout`. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the file descriptor, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now we want to redirect this status message into a file named `status.txt`. As we do it before, we can use `file descriptors`! Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;`! But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with following command:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
# Real World Example&lt;br /&gt;
&lt;br /&gt;
Welcome! This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=153</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=153"/>
		<updated>2024-12-16T14:32:23Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a small tutorial about UNIX pipes, a powerful way to combine multiple commands together.&lt;br /&gt;
&lt;br /&gt;
== Basic Unix Commands and Concepts ==&lt;br /&gt;
&lt;br /&gt;
Reminder about basic commands:&lt;br /&gt;
&lt;br /&gt;
=== cd (Change Directory): ===&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 cd documents&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
 cd ../directory_path&lt;br /&gt;
&lt;br /&gt;
=== ls (List Directory Contents) ===&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ls&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
- `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
- `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
## mkdir (Creating Directories)&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing.&lt;br /&gt;
You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
mkdir &#039;directory_path&#039;&lt;br /&gt;
```&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
mkdir my_new_directory&lt;br /&gt;
```&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
*other folders or files&lt;br /&gt;
my_new_directory&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v`! The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later!&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
mkdir -v my_new_directory&lt;br /&gt;
```&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
## htop&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
htop&lt;br /&gt;
```&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
The best thing (for me) `htop` providing is the `with mouse navigating`. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
## time&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
# stdout, stdin and stderr&lt;br /&gt;
&lt;br /&gt;
## stdout (Standard Output)&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Lets say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
Cool, right? But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works for us, it kinda seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly `file descriptors` of Linux. Using file descriptors is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and file descriptors, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic `file descriptors` in Linux. Using it like that, you will redirect the `output` of the program into a file. In detail, we will talk about it in next chapters.&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to delete the output of the program. You can do this again using file descriptors. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
## stdin (Standard Input)&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, &amp;quot;legally&amp;quot;, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py ozgur&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Aaaaand it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Well, that&#039;s a huge modification at all. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py ozgur&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! ozgur&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little programme). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using file descriptors, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using pipes like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
or with file descriptors:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to file descriptors.&lt;br /&gt;
&lt;br /&gt;
## stderr (Standard Error)&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with print function like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the `status message` is still going to `stdout`. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the file descriptor, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now we want to redirect this status message into a file named `status.txt`. As we do it before, we can use `file descriptors`! Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;`! But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with following command:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
# Real World Example&lt;br /&gt;
&lt;br /&gt;
Welcome! This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_2_answers&amp;diff=152</id>
		<title>SNP calling exercise part 2 answers</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_2_answers&amp;diff=152"/>
		<updated>2024-12-15T15:28:55Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;Q1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First running:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk VariantFiltration     -V NA24694.vcf.gz  -O NA24694_hf.vcf.gz   -filter &amp;quot;DP &amp;lt; 10.0&amp;quot; --filter-name &amp;quot;DP&amp;quot;    -filter &amp;quot;QUAL &amp;lt; 30.0&amp;quot; --filter-name &amp;quot;QUAL30&amp;quot;     -filter &amp;quot;SOR &amp;gt; 3.0&amp;quot; --filter-name &amp;quot;SOR3&amp;quot;     -filter &amp;quot;FS &amp;gt; 60.0&amp;quot; --filter-name &amp;quot;FS60&amp;quot;     -filter &amp;quot;MQ &amp;lt; 40.0&amp;quot; --filter-name &amp;quot;MQ40&amp;quot;      &lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 bcftools view  -H NA24694_hf.vcf.gz |grep -v PASS |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gives us 4005 sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 bcftools view  -H  --type=snps NA24694_hf.vcf.gz |grep -v PASS |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
2630 SNPs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
One possibility is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 bcftools view -H NA24694_hf.vcf.gz |grep -v PASS |cut -f 7  |sort |uniq -c  |sort -n &lt;br /&gt;
      5 FS60;SOR3&lt;br /&gt;
     30 DP;MQ40;SOR3&lt;br /&gt;
     74 MQ40;SOR3&lt;br /&gt;
    158 DP;SOR3&lt;br /&gt;
    197 DP;MQ40&lt;br /&gt;
    390 MQ40&lt;br /&gt;
   1340 SOR3&lt;br /&gt;
   1811 DP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This says remove all lines with the string &amp;quot;PASS&amp;quot;, extract the seventh column, sort them, unique and count them, sort again but according to numerical order. At the bottom, you have the most used filter which is depth of coverage.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we isolate the ones that pass the filter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view  -f PASS NA24694_hf.vcf.gz |bgzip -c  &amp;gt; NA24694_hf_pass.vcf.gz&lt;br /&gt;
bcftools view -H NA24694_hf_pass.vcf.gz |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
88594 total sites (SNPS+indels+multi-allelic).&lt;br /&gt;
&lt;br /&gt;
Then we retain the sites using bedtools:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bedtools intersect -header -a  NA24694_hf_pass.vcf.gz  -b /home/databases/databases/GRCh38/filter99.bed.gz |bgzip -c &amp;gt; NA24694_hf_map99.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view -H NA24694_hf_map99.vcf.gz |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
51624 total sites remain&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q4&#039;&#039;&#039;&lt;br /&gt;
Using:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
java -jar /home/ctools/snpEff/snpEff.jar  eff  -dataDir /home/databases/databases/snpEff/  -htmlStats NA24694_hf.html GRCh38.99 NA24694_hf.vcf.gz  |bgzip -c &amp;gt; NA24694_hf_ann.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the HTML file you see:&lt;br /&gt;
Intron 64.368% &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q5&#039;&#039;&#039;&lt;br /&gt;
In the HTML file you see:&lt;br /&gt;
&lt;br /&gt;
MISSENSE 584 	44.242% &lt;br /&gt;
&lt;br /&gt;
So a total of 584 detecting mutations can have an impact on the protein sequence.&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_2_answers&amp;diff=151</id>
		<title>SNP calling exercise part 2 answers</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_2_answers&amp;diff=151"/>
		<updated>2024-12-15T15:28:16Z</updated>

		<summary type="html">&lt;p&gt;Gabre: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Q1&amp;#039;&amp;#039;&amp;#039;  First, running: &amp;lt;pre&amp;gt; tabix -f -p vcf NA24694.gvcf.gz &amp;lt;/pre&amp;gt; then &amp;lt;pre&amp;gt; gatk --java-options &amp;quot;-Xmx10g&amp;quot; HaplotypeCaller    -R /home/databases/references/human/GRCh38_full_analysis_set_plus_decoy_hla.fa    -I /home/projects/22126_NGS/exercises/snp_calling/NA24694.bam  -L chr20  -O NA24694.gvcf.gz  --dbsnp  /home/databases/databases/GRCh38/Homo_sapiens_assembly38.dbsnp138.vcf.gz  -ERC GVCF  &amp;lt;/pre&amp;gt;  &amp;lt;pre&amp;gt; gatk  GenotypeGVCFs -R /home/databases/references/human/GRCh3...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Q1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First, running:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix -f -p vcf NA24694.gvcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
then&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk --java-options &amp;quot;-Xmx10g&amp;quot; HaplotypeCaller    -R /home/databases/references/human/GRCh38_full_analysis_set_plus_decoy_hla.fa    -I /home/projects/22126_NGS/exercises/snp_calling/NA24694.bam  -L chr20  -O NA24694.gvcf.gz  --dbsnp  /home/databases/databases/GRCh38/Homo_sapiens_assembly38.dbsnp138.vcf.gz  -ERC GVCF &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk  GenotypeGVCFs -R /home/databases/references/human/GRCh38_full_analysis_set_plus_decoy_hla.fa -V NA24694.gvcf.gz  -L chr20 --dbsnp  /home/databases/databases/GRCh38/Homo_sapiens_assembly38.dbsnp138.vcf.gz -O NA24694.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools stats  NA24694.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should give you:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SN	0	number of SNPs:	75684&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
so 75684 SNPs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix -p vcf NA24694.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix  NA24694.vcf.gz chr20:32000000-33000000 |wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So 1290 variant sites.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are 2 ways to do this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view -H --type=snps NA24694.vcf.gz  chr20:32000000-33000000 |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix -h NA24694.vcf.gz chr20:32000000-33000000 |bcftools view -H --type=snps -  |wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Both will give you: 956.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix NA24694.vcf.gz  chr20:32011209-32011209&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You get:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chr20	32011209	rs147652161	G	A	264.64	.	AC=1;AF=0.500;AN=2;BaseQRankSum=-3.010e-01;DB;DP=24;ExcessHet=3.0103;FS=3.949;MLEAC=1;MLEAF=0.500;MQ=60.00;MQRankSum=0.00;QD=11.03;ReadPosRankSum=-3.580e-01;SOR=0.552	GT:AD:DP:GQ:PL	0/1:15,9:24:99:272,0,533&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The line above says that you probably have G and A and the site is heterozygous. G is the reference and A the alternative allele. The allele depth is 15Gs, 9As, the depth is 24, the genotype quality is 99, the PHRED genotype likelihoods are homo ref, hetero, homo alt: 272,0,533&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix NA24694.vcf.gz  chr20:32044279-32044279&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You get:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chr20	32044279	rs4525768	C	T	799.06	.	AC=2;AF=1.00;AN=2;DB;DP=21;ExcessHet=3.0103;FS=0.000;MLEAC=2;MLEAF=1.00;MQ=60.00;QD=28.99;SOR=0.990	GT:AD:DP:GQ:PL	1/1:0,21:21:63:813,63,0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The line above says that you are probably homozygous for T. C is the reference and T the alternative allele. The allele depth is 0Cs, 21Ts, the depth is 21, the genotype quality is 63, the PHRED genotype likelihoods are homo ref, hetero, homo alt: 813,63,0. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q5&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Both are heterozygous sites however this is the better one:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chr20	32974911	rs6088051	A	G	403.64	.	AC=1;AF=0.500;AN=2;BaseQRankSum=0.693;DB;DP=22;ExcessHet=3.0103;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=59.78;MQRankSum=-6.860e-01;QD=19.22;ReadPosRankSum=-1.703e+00;SOR=0.871	GT:AD:DP:GQ:PL	0/1:8,13:21:99:411,0,247&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the worse one:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chr20	64291638	rs369221086	C	T	30.64	.	AC=1;AF=0.500;AN=2;BaseQRankSum=-2.530e-01;DB;DP=6;ExcessHet=3.0103;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=28.18;MQRankSum=-9.670e-01;QD=5.11;ReadPosRankSum=-8.420e-01;SOR=0.693	GT:AD:DP:GQ:PL	0/1:4,2:6:38:38,0,114&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first site has a depth of 21, 8As and 13Gs. In the second case, the genotype quality is 38 and the first was 99. The second one only has 4Cs and 2 Ts for a total depth of 6 which is not sufficient to confidently call a heterozygous site. &lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&#039;&#039;&#039;Q6&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Either use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view -H --types=snps  NA24694.vcf.gz chr20:32000000-33000000 |cut -f 3 |grep -v rs |wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view -H --types=snps  NA24694.vcf.gz chr20:32000000-33000000 |cut -f 3 |grep &amp;quot;\.&amp;quot; |wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
you will get 17. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q7&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
17 is very little compared to the number of SNPs 956. However, this is very expected. Given that the individual is Han Chinese, this ethnic group is very well represented in dbSNP.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir var_recal/&lt;br /&gt;
gatk --java-options &amp;quot;-Xmx10G&amp;quot;   VariantRecalibrator -V NA24694.vcf.gz    --rscript-file var_recal/NA24694_plots.R -O var_recal/NA24694_recal  -mode SNP --tranches-file var_recal/NA24694_tranches   -tranche 99.0  -tranche 95.0 -tranche 90.0  -tranche 85.0 -tranche 80.0 -tranche 75.0 -tranche 70.0 -tranche 65.0 -tranche 60.0 -tranche 58.0  -an QD -an DP -an FS  -an MQRankSum -an ReadPosRankSum -an SOR -an MQ  -resource:hapmap,known=false,training=true,truth=true,prior=15.0 /home/databases/databases/GRCh38/hapmap_3.3.hg38.vcf.gz   -resource:omni,known=false,training=true,truth=false,prior=12.0 /home/databases/databases/GRCh38/1000G_omni2.5.hg38.vcf.gz   -resource:1000G,known=false,training=true,truth=false,prior=10.0 /home/databases/databases/GRCh38/1000G_phase1.snps.high_confidence.hg38.vcf.gz    -resource:dbsnp,known=true,training=false,truth=false,prior=2.0 /home/databases/databases/GRCh38/Homo_sapiens_assembly38.dbsnp138.vcf.gz &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q8&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Either 60 or 65 should be good. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 gatk --java-options &amp;quot;-Xmx10G&amp;quot; ApplyVQSR -V NA24694.vcf.gz  -O NA24694_sf.vcf.gz --recal-file var_recal/NA24694_recal  --tranches-file var_recal/NA24694_tranches  -truth-sensitivity-filter-level 65 --create-output-variant-index true  -mode SNP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q9&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Let us not forget to index:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix -p  vcf NA24694_sf_pass.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view -H --types=snps  NA24694_sf_pass.vcf.gz  chr20:32000000-33000000 |wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
For a total of filtered 416 SNPs which is much less of them before.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q10&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
If you are more sensitive then you will let more sites through and the number would increase.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q11&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First running:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk VariantFiltration     -V NA24694.vcf.gz  -O NA24694_hf.vcf.gz   -filter &amp;quot;DP &amp;lt; 10.0&amp;quot; --filter-name &amp;quot;DP&amp;quot;    -filter &amp;quot;QUAL &amp;lt; 30.0&amp;quot; --filter-name &amp;quot;QUAL30&amp;quot;     -filter &amp;quot;SOR &amp;gt; 3.0&amp;quot; --filter-name &amp;quot;SOR3&amp;quot;     -filter &amp;quot;FS &amp;gt; 60.0&amp;quot; --filter-name &amp;quot;FS60&amp;quot;     -filter &amp;quot;MQ &amp;lt; 40.0&amp;quot; --filter-name &amp;quot;MQ40&amp;quot;      &lt;br /&gt;
  &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 bcftools view  -H NA24694_hf.vcf.gz |grep -v PASS |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gives us 4005 sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 bcftools view  -H  --type=snps NA24694_hf.vcf.gz |grep -v PASS |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
2630 SNPs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q12&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
One possibility is:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 bcftools view -H NA24694_hf.vcf.gz |grep -v PASS |cut -f 7  |sort |uniq -c  |sort -n &lt;br /&gt;
      5 FS60;SOR3&lt;br /&gt;
     30 DP;MQ40;SOR3&lt;br /&gt;
     74 MQ40;SOR3&lt;br /&gt;
    158 DP;SOR3&lt;br /&gt;
    197 DP;MQ40&lt;br /&gt;
    390 MQ40&lt;br /&gt;
   1340 SOR3&lt;br /&gt;
   1811 DP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This says remove all lines with the string &amp;quot;PASS&amp;quot;, extract the seventh column, sort them, unique and count them, sort again but according to numerical order. At the bottom, you have the most used filter which is depth of coverage.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q13&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Initially, we isolate the ones that pass the filter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view  -f PASS NA24694_hf.vcf.gz |bgzip -c  &amp;gt; NA24694_hf_pass.vcf.gz&lt;br /&gt;
bcftools view -H NA24694_hf_pass.vcf.gz |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
88594 total sites (SNPS+indels+multi-allelic).&lt;br /&gt;
&lt;br /&gt;
Then we retain the sites using bedtools:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bedtools intersect -header -a  NA24694_hf_pass.vcf.gz  -b /home/databases/databases/GRCh38/filter99.bed.gz |bgzip -c &amp;gt; NA24694_hf_map99.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view -H NA24694_hf_map99.vcf.gz |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
51624 total sites remain&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q14&#039;&#039;&#039;&lt;br /&gt;
Using:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
java -jar /home/ctools/snpEff/snpEff.jar  eff  -dataDir /home/databases/databases/snpEff/  -htmlStats NA24694_hf.html GRCh38.99 NA24694_hf.vcf.gz  |bgzip -c &amp;gt; NA24694_hf_ann.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the HTML file you see:&lt;br /&gt;
Intron 64.368% &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q15&#039;&#039;&#039;&lt;br /&gt;
In the HTML file you see:&lt;br /&gt;
&lt;br /&gt;
MISSENSE 584 	44.242% &lt;br /&gt;
&lt;br /&gt;
So a total of 584 detecting mutations can have an impact on the protein sequence.&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_1_answers&amp;diff=150</id>
		<title>SNP calling exercise part 1 answers</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_1_answers&amp;diff=150"/>
		<updated>2024-12-15T15:27:53Z</updated>

		<summary type="html">&lt;p&gt;Gabre: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;Q1&amp;#039;&amp;#039;&amp;#039;  First, running: &amp;lt;pre&amp;gt; tabix -f -p vcf NA24694.gvcf.gz &amp;lt;/pre&amp;gt; then &amp;lt;pre&amp;gt; gatk --java-options &amp;quot;-Xmx10g&amp;quot; HaplotypeCaller    -R /home/databases/references/human/GRCh38_full_analysis_set_plus_decoy_hla.fa    -I /home/projects/22126_NGS/exercises/snp_calling/NA24694.bam  -L chr20  -O NA24694.gvcf.gz  --dbsnp  /home/databases/databases/GRCh38/Homo_sapiens_assembly38.dbsnp138.vcf.gz  -ERC GVCF  &amp;lt;/pre&amp;gt;  &amp;lt;pre&amp;gt; gatk  GenotypeGVCFs -R /home/databases/references/human/GRCh3...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Q1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First, running:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix -f -p vcf NA24694.gvcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
then&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk --java-options &amp;quot;-Xmx10g&amp;quot; HaplotypeCaller    -R /home/databases/references/human/GRCh38_full_analysis_set_plus_decoy_hla.fa    -I /home/projects/22126_NGS/exercises/snp_calling/NA24694.bam  -L chr20  -O NA24694.gvcf.gz  --dbsnp  /home/databases/databases/GRCh38/Homo_sapiens_assembly38.dbsnp138.vcf.gz  -ERC GVCF &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk  GenotypeGVCFs -R /home/databases/references/human/GRCh38_full_analysis_set_plus_decoy_hla.fa -V NA24694.gvcf.gz  -L chr20 --dbsnp  /home/databases/databases/GRCh38/Homo_sapiens_assembly38.dbsnp138.vcf.gz -O NA24694.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools stats  NA24694.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Should give you:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SN	0	number of SNPs:	75684&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
so 75684 SNPs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix -p vcf NA24694.vcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix  NA24694.vcf.gz chr20:32000000-33000000 |wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
So 1290 variant sites.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are 2 ways to do this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view -H --type=snps NA24694.vcf.gz  chr20:32000000-33000000 |wc -l &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix -h NA24694.vcf.gz chr20:32000000-33000000 |bcftools view -H --type=snps -  |wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Both will give you: 956.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix NA24694.vcf.gz  chr20:32011209-32011209&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You get:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chr20	32011209	rs147652161	G	A	264.64	.	AC=1;AF=0.500;AN=2;BaseQRankSum=-3.010e-01;DB;DP=24;ExcessHet=3.0103;FS=3.949;MLEAC=1;MLEAF=0.500;MQ=60.00;MQRankSum=0.00;QD=11.03;ReadPosRankSum=-3.580e-01;SOR=0.552	GT:AD:DP:GQ:PL	0/1:15,9:24:99:272,0,533&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The line above says that you probably have G and A and the site is heterozygous. G is the reference and A the alternative allele. The allele depth is 15Gs, 9As, the depth is 24, the genotype quality is 99, the PHRED genotype likelihoods are homo ref, hetero, homo alt: 272,0,533&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix NA24694.vcf.gz  chr20:32044279-32044279&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
You get:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chr20	32044279	rs4525768	C	T	799.06	.	AC=2;AF=1.00;AN=2;DB;DP=21;ExcessHet=3.0103;FS=0.000;MLEAC=2;MLEAF=1.00;MQ=60.00;QD=28.99;SOR=0.990	GT:AD:DP:GQ:PL	1/1:0,21:21:63:813,63,0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The line above says that you are probably homozygous for T. C is the reference and T the alternative allele. The allele depth is 0Cs, 21Ts, the depth is 21, the genotype quality is 63, the PHRED genotype likelihoods are homo ref, hetero, homo alt: 813,63,0. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q5&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Both are heterozygous sites however this is the better one:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chr20	32974911	rs6088051	A	G	403.64	.	AC=1;AF=0.500;AN=2;BaseQRankSum=0.693;DB;DP=22;ExcessHet=3.0103;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=59.78;MQRankSum=-6.860e-01;QD=19.22;ReadPosRankSum=-1.703e+00;SOR=0.871	GT:AD:DP:GQ:PL	0/1:8,13:21:99:411,0,247&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the worse one:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chr20	64291638	rs369221086	C	T	30.64	.	AC=1;AF=0.500;AN=2;BaseQRankSum=-2.530e-01;DB;DP=6;ExcessHet=3.0103;FS=0.000;MLEAC=1;MLEAF=0.500;MQ=28.18;MQRankSum=-9.670e-01;QD=5.11;ReadPosRankSum=-8.420e-01;SOR=0.693	GT:AD:DP:GQ:PL	0/1:4,2:6:38:38,0,114&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first site has a depth of 21, 8As and 13Gs. In the second case, the genotype quality is 38 and the first was 99. The second one only has 4Cs and 2 Ts for a total depth of 6 which is not sufficient to confidently call a heterozygous site. &lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
&#039;&#039;&#039;Q6&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Either use:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view -H --types=snps  NA24694.vcf.gz chr20:32000000-33000000 |cut -f 3 |grep -v rs |wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view -H --types=snps  NA24694.vcf.gz chr20:32000000-33000000 |cut -f 3 |grep &amp;quot;\.&amp;quot; |wc -l&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
you will get 17. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q7&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
17 is very little compared to the number of SNPs 956. However, this is very expected. Given that the individual is Han Chinese, this ethnic group is very well represented in dbSNP.&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_1&amp;diff=149</id>
		<title>SNP calling exercise part 1</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_1&amp;diff=149"/>
		<updated>2024-12-15T15:27:20Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;H2&amp;gt;Overview&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First:&lt;br /&gt;
&amp;lt;OL&amp;gt;&lt;br /&gt;
&amp;lt;LI&amp;gt;Navigate to your home directory:&lt;br /&gt;
&amp;lt;LI&amp;gt;Create a directory called &amp;quot;variant_call&amp;quot; &lt;br /&gt;
&amp;lt;LI&amp;gt;Navigate to the directory you just created.&lt;br /&gt;
&amp;lt;/OL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will:&lt;br /&gt;
&amp;lt;OL&amp;gt;&lt;br /&gt;
&amp;lt;LI&amp;gt;Genotype some whole-genome sequencing data.&lt;br /&gt;
&amp;lt;LI&amp;gt;Get acquainted with VCF files&lt;br /&gt;
&amp;lt;LI&amp;gt;Soft filtering&lt;br /&gt;
&amp;lt;LI&amp;gt;Hard filtering&lt;br /&gt;
&amp;lt;LI&amp;gt; Annotation of variants&lt;br /&gt;
&amp;lt;/OL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H2&amp;gt;Genotyping&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will genotype a chromosome from a BAM file that has been processed using the steps we detailed before. It is from a [https://en.wikipedia.org/wiki/Han_Chinese Han Chinese] Male with a depth of coverage of 24.6X. &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 /home/projects/22126_NGS/exercises/snp_calling/NA24694.bam&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It has been indexed. We will first use GATK&#039;s HaplotypeCaller, the command-line look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk --java-options &amp;quot;-Xmx10g&amp;quot; HaplotypeCaller    -R /home/databases/references/human/GRCh38_full_analysis_set_plus_decoy_hla.fa    -I  [INPUT BAM]  -L chr20  -O  [OUTPUT ] --dbsnp /home/databases/databases/GRCh38/Homo_sapiens_assembly38.dbsnp138.vcf.gz  -ERC GVCF &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot; -R /home/databases/references/human/GRCh38_full_analysis_set_plus_decoy_hla.fa &amp;quot; specifies a reference, &amp;quot;-L chr20&amp;quot; specifies only to consider chromosome 20, &amp;quot;-dbsnp /home/databases/databases/GRCh38/Homo_sapiens_assembly38.dbsnp138.vcf.gz &amp;quot;, add annotation from SNPs which are known to exist in the human population (see [https://www.ncbi.nlm.nih.gov/snp/ dbSNP]). We should point out that the variation coming from Eurasians is more extensively represented in this database. However, the most genetically diverse populations are found in [https://genomebiology.biomedcentral.com/articles/10.1186/s13059-019-1740-1 Africa]. Finally, &amp;quot; -ERC GVCF&amp;quot; will generate a GVCF (Genomic Variant Call Format) which essentially contains all sites instead of just variant sites. The input is specified above, you can call the output: NA24694.gvcf.gz&lt;br /&gt;
&lt;br /&gt;
The command takes between &#039;&#039;&#039;20 to 30 minutes to run&#039;&#039;&#039;, so feel free to take a break. Or feel free to copy the one I generated:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 /home/projects/22126_NGS/exercises/snp_calling/NA24694.gvcf.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will have a brief look at the file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zcat NA24694.gvcf.gz|less -S&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will see several lines starting with &#039;#&#039;, this is the header portion, scroll down to see the calls. The first 5 columns represent, the name of the chromosome, the coordinate, snp ID (from dbSNP), the reference base and the alternative base.  You should see a mix of sites, some with the mention &amp;lt;NON_REF&amp;gt; in the 5th column which corresponds to the alternative base, those sites are probably invariant, and others where there is a variant in the fifth column. &lt;br /&gt;
&lt;br /&gt;
Prior to running GATK, we need to index it:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix -f -p vcf [VCF to index]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we will use the preliminary variant to actually generate only variant sites:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk  GenotypeGVCFs -R /home/databases/references/human/GRCh38_full_analysis_set_plus_decoy_hla.fa -V [INPUT GVCF]  -O [OUTPUT VCF]  -L chr20 --dbsnp  /home/databases/databases/GRCh38/Homo_sapiens_assembly38.dbsnp138.vcf.gz &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your case, the input is the file you generated above and the output can be called NA24694.vcf.gz.&lt;br /&gt;
This command takes less than 5 minutes to run. &lt;br /&gt;
&lt;br /&gt;
Then let us index the file with the same tabix command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix -f -p vcf [VCF to index]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just like &amp;quot;samtools index&amp;quot; can allow us to create an index to retrieve portions of a BAM file, tabix is another utility that allows us to retrieve portions of a GVCF file. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt; Get acquainted with VCF files &amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools stats  [input vcf]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
How many SNPs do you have? (hint: find the line with: &amp;quot;SN	0	number of SNPs&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix -f -p vcf [VCF to index]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The index will be stored as a &amp;quot;tbi&amp;quot; file. Then, the VCF file can be queried:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix  [VCF to index] [CHROMOSOME]:[START]-[END]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where [CHROMOSOME] is the chromosome name and [START] [END] are the start and end coordinates respectively. &lt;br /&gt;
Or for a single coordinate:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tabix  [VCF to index] [CHROMOSOME]:[COORDINATE]-[COORDINATE]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Use the command above, determine how many total variants are in the 1 million base pair region &amp;quot;chr20:32000000-33000000&amp;quot;? (hint, remember &amp;quot;wc -l&amp;quot; to count lines).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q3&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
bcftools is a nifty utility that allows us to do various operations on VCF files. Type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcftools view&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
It contains several options. Try to determine how many SNPs (excluding indels and multi-allelic sites) are there in the &#039;&#039;&#039;same region&#039;&#039;&#039; as above? (hint: you need to filter for a certain &#039;&#039;&#039;type&#039;&#039;&#039; of variant, hint2: be careful not to include the header in the number of lines (option: -H)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q4&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Use either tabix or bcftools to retrieve the SNP located on chromosome 20 at coordinate 32011209. Tell me in your own words what is the genotype? What about chromosome 20, coordinate 32044279. Become familiar with the different fields in the [https://samtools.github.io/hts-specs/VCFv4.2.pdf VCF specifications]. Pay attention to &amp;quot;1.4 Data lines&amp;quot;. For the genotype fields (column 9 and 10) there are more info on the GATK fields: [https://gatk.broadinstitute.org/hc/en-us/articles/360035531692-VCF-Variant-Call-Format GATK&#039;s VCF-Variant-Call-Format]. &lt;br /&gt;
&lt;br /&gt;
Also, answer for each site:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;OL&amp;gt;&lt;br /&gt;
&amp;lt;LI&amp;gt; what is the allele depth i.e. how many bases are there of each type?&lt;br /&gt;
&amp;lt;LI&amp;gt; what is the depth of coverage i.e. how many bases cover this site?&lt;br /&gt;
&amp;lt;LI&amp;gt; What is your genotype quality?&lt;br /&gt;
&amp;lt;LI&amp;gt; What are your genotype likelihoods? &lt;br /&gt;
&amp;lt;/OL&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Q5&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Inspect the SNPS at positions:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
chr20	32974911&lt;br /&gt;
chr20	64291638&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One SNP has poor quality the other has good quality. Which is which? Why do you think this is? (hint: remember the class, the more data you have, the more you are sure). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q6&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Using the same region, 32000000-33000000, how many are novel (i.e. does not exist in databases of a large number of sampled genomed) SNPs? Note that the third column is the ID of a known SNP in dbSNP. You can use the &#039;&#039;&#039;cut&#039;&#039;&#039;  command to get a specific column. Also, every ID in dbSNP starts with &amp;quot;rs&amp;quot; and you could use &#039;&#039;&#039;grep&#039;&#039;&#039; to either retain such lines or filter them out (see option -v).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q7&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Contrast the number you obtained for questions 6 to the one you obtained for question 3. Do you think it&#039;s expected?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Congratulations you finished the exercise!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Please find answers [[SNP_calling_exercise_part_1_answers_|here]]&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_2&amp;diff=148</id>
		<title>SNP calling exercise part 2</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_2&amp;diff=148"/>
		<updated>2024-12-15T15:27:18Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&amp;lt;H2&amp;gt; Filtering&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We saw that the data contains some calls of poor quality. Ideally, we do not want to carry over these calls into downstream analyses. We will explore how to filter out genotype data.&lt;br /&gt;
&lt;br /&gt;
Please use the VCF file generated in part 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt; Hard filtering &amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We saw that soft filtering learns which variants are &amp;quot;true.&amp;quot; However, a major downside of soft filtering is that it does not apply to samples for which we do not have a good representation of the genetic diversity. &lt;br /&gt;
&lt;br /&gt;
An alternative is to do hard filtering i.e. filtering the variants according to predetermined cutoffs. This has the downside of potentially introducing bias if the filter is correlated with the type of variant (ex: if heterozygous sites have higher genotype quality). &lt;br /&gt;
&lt;br /&gt;
First, we will consider the following mask file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/home/databases/databases/GRCh38/mask99.bed.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is in BED format which is for genomic intervals. These files are extensively used in next-generation sequencing analyses, have a look at the first lines, the format is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[chromosome] [start coordinate (0-based)] [end coordinate (1-based)] &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
0-based means that the first base is at coordinates 0 (i.e 0 1 2 3 ...), 1-based means that the first base is at coordinate 1 (i.e 1 2 3 4...).&lt;br /&gt;
&lt;br /&gt;
This mask file contains a set of genomic regions that you want to &#039;&#039;&#039;remove&#039;&#039;&#039; from downstream analyses. It is important to note that most genotypers do not take into account the fact that a genomic region can be duplicated. This is why it&#039;s that a mappability filter is also a good idea to use.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk VariantFiltration     -V [INPUT VCF]  -O [OUTPUT VCF]   -filter &amp;quot;DP &amp;lt; 10.0&amp;quot; --filter-name &amp;quot;DP&amp;quot;    -filter &amp;quot;QUAL &amp;lt; 30.0&amp;quot; --filter-name &amp;quot;QUAL30&amp;quot;     -filter &amp;quot;SOR &amp;gt; 3.0&amp;quot; --filter-name &amp;quot;SOR3&amp;quot;     -filter &amp;quot;FS &amp;gt; 60.0&amp;quot; --filter-name &amp;quot;FS60&amp;quot;     -filter &amp;quot;MQ &amp;lt; 40.0&amp;quot; --filter-name &amp;quot;MQ40&amp;quot;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is what the different filter mean:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| &#039;&#039;&#039;Filter&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Meaning&#039;&#039;&#039;    &lt;br /&gt;
|-&lt;br /&gt;
| -filter &amp;quot;DP &amp;lt; 10.0&amp;quot; &lt;br /&gt;
| sites with less than 10X depth of coverage are removed&lt;br /&gt;
|-&lt;br /&gt;
| -filter &amp;quot;QUAL &amp;lt; 30.0&amp;quot; &lt;br /&gt;
| sites with a variant quality less than 30 are removed (see the difference between variant quality and genotype quality (GQ) [https://gatk.broadinstitute.org/hc/en-us/articles/360035531392?id=7258 here] )&lt;br /&gt;
|-&lt;br /&gt;
| -filter &amp;quot;SOR &amp;gt; 3.0&amp;quot;&lt;br /&gt;
| sites with a strand odds ratio less than 3.0 are removed (strand bias is when a strand is favored over the other, read more [https://gatk.broadinstitute.org/hc/en-us/articles/360036361772-StrandOddsRatio here] )&lt;br /&gt;
|-&lt;br /&gt;
| -filter &amp;quot;FS &amp;gt; 60.0&amp;quot; &lt;br /&gt;
| sites with a Fisher&#039;s exact test (FS) for strand bias is greater than 60 are removed (read more about FS [https://gatk.broadinstitute.org/hc/en-us/articles/360036361992-FisherStrand here] ).&lt;br /&gt;
|-&lt;br /&gt;
| -filter &amp;quot;MQ &amp;lt; 40.0&amp;quot; &lt;br /&gt;
|sites where the median mapping quality of reads supporting is less than 40 are removed.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In real life, there are no perfect filters, I suggest you progressively add them, measure their effectiveness and make sure that you do not introduce unwanted bias to your analyses. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
How many sites have been filtered out? Remember that sites that passed the filter will have the string &#039;&#039;&#039;PASS&#039;&#039;&#039; as the seventh column, you can use &#039;&#039;&#039;grep&#039;&#039;&#039; with the trick we mentioned to remove lines with a specific string. How many SNPs were filtered out?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The filtering command leaves in the seventh column a string (specified via --filter-name above) to determine which filter failed sites that were removed. Can you use the command above and modify it using the commands like &#039;&#039;&#039;cut&#039;&#039;&#039;, &#039;&#039;&#039;sort&#039;&#039;&#039; and &#039;&#039;&#039;uniq&#039;&#039;&#039; to determine was the filter that filtered out the most sites? If you are starting to use UNIX, this question might be challenging.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s further remove sites that are in genomic regions of poor mappability. We can use bedtools which is a set of utilities to deal with BED files (merge, intersect, etc). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bedtools intersect -header -a  [INPUT VCF] -b /home/databases/databases/GRCh38/filter99.bed.gz |bgzip -c &amp;gt; [OUTPUT VCF]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;-header&amp;quot; just says print the header of [INPUT VCF]. Retain the sites that have &#039;&#039;&#039;passed the hard filtering&#039;&#039;&#039; that are contained in filter99.bed.gz and call the output NA24694_hf_map99.vcf.gz. The 99 is from the percentage of DNA fragments required to map uniquely at that particular position (read more [http://lh3lh3.users.sourceforge.net/snpable.shtml here]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
How many sites did you retain? &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H2&amp;gt;Annotation of variants&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An interesting question is always would was the genomic context of the variants, are they in introns, exons, intergenic. We will use a program called snpEff to characterize the different genomic variants that we found. You can run the program as such:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
java -jar /home/ctools/snpEff/snpEff.jar  eff  -dataDir /home/databases/databases/snpEff/  -htmlStats [OUTPUT HTML] GRCh38.99 [INPUT VCF]  |bgzip -c &amp;gt; [OUTPUT VCF]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -dataDir option specifies where to find the data. A human gene database was downloaded here: /home/databases/databases/snpEff/. &amp;quot;GRCh38.99&amp;quot; represents a specific version (hg38) of the human genome. As mentioned in previous exercises, be very careful to use the exact same version of the genome in your analyses.&lt;br /&gt;
&lt;br /&gt;
Run it on file resulting from hard-filtering prior to the filtering by mappability (NA24694_hf.vcf.gz), create an output HTML named: NA24694_hf.html and a VCF output named: NA24694_hf_ann.vcf.gz.&lt;br /&gt;
&lt;br /&gt;
Use firefox to open the HTML report:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
firefox NA24694_hf.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and answer the following questions:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q4&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
What is the most common genomic region (exon, downstream, intron, UTR) of the variants we detected? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q5&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
How many variants can lead to a codon change? See explanation about point mutations on [https://en.wikipedia.org/wiki/Point_mutation Wikipedia]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Please find answers [[SNP_calling_exercise_part_2_answers|here]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Congratulations you finished the exercise!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: in these exercises and answers, sometimes piped the output of &amp;quot;bcftools view&amp;quot; into other programs, ideally you should use the flag:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-O,   --output-type &amp;lt;b|u|z|v&amp;gt;       b: compressed BCF, u: uncompressed BCF, z: compressed VCF, v: uncompressed VCF [v]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and think about which one is appropriate for your situation whether you&#039;re storing data or piping to another program.&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_2&amp;diff=147</id>
		<title>SNP calling exercise part 2</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=SNP_calling_exercise_part_2&amp;diff=147"/>
		<updated>2024-12-15T15:25:08Z</updated>

		<summary type="html">&lt;p&gt;Gabre: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&amp;lt;H2&amp;gt; Filtering&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We saw that the data contains some calls of poor quality. Ideally, we do not want to carry over these calls into downstream analyses. We will explore how to filter out genotype data.&lt;br /&gt;
&lt;br /&gt;
Please use the vcf file generated in part 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H3&amp;gt; Hard filtering &amp;lt;/H3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We saw that soft filtering learns which variants are &amp;quot;true.&amp;quot; However, a major downside of soft filtering is that it does not apply to samples for which we do not have a good representation of the genetic diversity. &lt;br /&gt;
&lt;br /&gt;
An alternative is to do hard filtering i.e. filtering the variants according to predetermined cutoffs. This has the downside of potentially introducing bias if the filter is correlated with the type of variant (ex: if heterozygous sites have higher genotype quality). &lt;br /&gt;
&lt;br /&gt;
First, we will consider the following mask file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/home/databases/databases/GRCh38/mask99.bed.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is in BED format which is for genomic intervals. These files are extensively used in next-generation sequencing analyses, have a look at the first lines, the format is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[chromosome] [start coordinate (0-based)] [end coordinate (1-based)] &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
0-based means that the first base is at coordinates 0 (i.e 0 1 2 3 ...), 1-based means that the first base is at coordinate 1 (i.e 1 2 3 4...).&lt;br /&gt;
&lt;br /&gt;
This mask file contains a set of genomic regions that you want to &#039;&#039;&#039;remove&#039;&#039;&#039; from downstream analyses. It is important to note that most genotypers do not take into account the fact that a genomic region can be duplicated. This is why it&#039;s that a mappability filter is also a good idea to use.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatk VariantFiltration     -V [INPUT VCF]  -O [OUTPUT VCF]   -filter &amp;quot;DP &amp;lt; 10.0&amp;quot; --filter-name &amp;quot;DP&amp;quot;    -filter &amp;quot;QUAL &amp;lt; 30.0&amp;quot; --filter-name &amp;quot;QUAL30&amp;quot;     -filter &amp;quot;SOR &amp;gt; 3.0&amp;quot; --filter-name &amp;quot;SOR3&amp;quot;     -filter &amp;quot;FS &amp;gt; 60.0&amp;quot; --filter-name &amp;quot;FS60&amp;quot;     -filter &amp;quot;MQ &amp;lt; 40.0&amp;quot; --filter-name &amp;quot;MQ40&amp;quot;    &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is what the different filter mean:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| &#039;&#039;&#039;Filter&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Meaning&#039;&#039;&#039;    &lt;br /&gt;
|-&lt;br /&gt;
| -filter &amp;quot;DP &amp;lt; 10.0&amp;quot; &lt;br /&gt;
| sites with less than 10X depth of coverage are removed&lt;br /&gt;
|-&lt;br /&gt;
| -filter &amp;quot;QUAL &amp;lt; 30.0&amp;quot; &lt;br /&gt;
| sites with a variant quality less than 30 are removed (see the difference between variant quality and genotype quality (GQ) [https://gatk.broadinstitute.org/hc/en-us/articles/360035531392?id=7258 here] )&lt;br /&gt;
|-&lt;br /&gt;
| -filter &amp;quot;SOR &amp;gt; 3.0&amp;quot;&lt;br /&gt;
| sites with a strand odds ratio less than 3.0 are removed (strand bias is when a strand is favored over the other, read more [https://gatk.broadinstitute.org/hc/en-us/articles/360036361772-StrandOddsRatio here] )&lt;br /&gt;
|-&lt;br /&gt;
| -filter &amp;quot;FS &amp;gt; 60.0&amp;quot; &lt;br /&gt;
| sites with a Fisher&#039;s exact test (FS) for strand bias is greater than 60 are removed (read more about FS [https://gatk.broadinstitute.org/hc/en-us/articles/360036361992-FisherStrand here] ).&lt;br /&gt;
|-&lt;br /&gt;
| -filter &amp;quot;MQ &amp;lt; 40.0&amp;quot; &lt;br /&gt;
|sites where the median mapping quality of reads supporting is less than 40 are removed.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In real life, there are no perfect filters, I suggest you progressively add them, measure their effectiveness and make sure that you do not introduce unwanted bias to your analyses. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q11&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
How many sites have been filtered out? Remember that sites that passed the filter will have the string &#039;&#039;&#039;PASS&#039;&#039;&#039; as the seventh column, you can use &#039;&#039;&#039;grep&#039;&#039;&#039; with the trick we mentioned to remove lines with a specific string. How many SNPs were filtered out?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q12&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The filtering command leaves in the seventh column a string (specified via --filter-name above) to determine which filter failed sites that were removed. Can you use the command above and modify it using the commands like &#039;&#039;&#039;cut&#039;&#039;&#039;, &#039;&#039;&#039;sort&#039;&#039;&#039; and &#039;&#039;&#039;uniq&#039;&#039;&#039; to determine was the filter that filtered out the most sites? If you are starting to use UNIX, this question might be challenging.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s further remove sites that are in genomic regions of poor mappability. We can use bedtools which is a set of utilities to deal with BED files (merge, intersect, etc). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bedtools intersect -header -a  [INPUT VCF] -b /home/databases/databases/GRCh38/filter99.bed.gz |bgzip -c &amp;gt; [OUTPUT VCF]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;-header&amp;quot; just says print the header of [INPUT VCF]. Retain the sites that have &#039;&#039;&#039;passed the hard filtering&#039;&#039;&#039; that are contained in filter99.bed.gz and call the output NA24694_hf_map99.vcf.gz. The 99 is from the percentage of DNA fragments required to map uniquely at that particular position (read more [http://lh3lh3.users.sourceforge.net/snpable.shtml here]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q13&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
How many sites did you retain? &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;H2&amp;gt;Annotation of variants&amp;lt;/H2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An interesting question is always would was the genomic context of the variants, are they in introns, exons, intergenic. We will use a program called snpEff to characterize the different genomic variants that we found. You can run the program as such:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
java -jar /home/ctools/snpEff/snpEff.jar  eff  -dataDir /home/databases/databases/snpEff/  -htmlStats [OUTPUT HTML] GRCh38.99 [INPUT VCF]  |bgzip -c &amp;gt; [OUTPUT VCF]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The -dataDir option specifies where to find the data. A human gene database was downloaded here: /home/databases/databases/snpEff/. &amp;quot;GRCh38.99&amp;quot; represents a specific version (hg38) of the human genome. As mentioned in previous exercises, be very careful to use the exact same version of the genome in your analyses.&lt;br /&gt;
&lt;br /&gt;
Run it on file resulting from hard-filtering prior to the filtering by mappability (NA24694_hf.vcf.gz), create an output HTML named: NA24694_hf.html and a VCF output named: NA24694_hf_ann.vcf.gz.&lt;br /&gt;
&lt;br /&gt;
Use firefox to open the HTML report:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
firefox NA24694_hf.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and answer the following questions:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q14&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
What is the most common genomic region (exon, downstream, intron, UTR) of the variants we detected? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q15&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
How many variants can lead to a codon change? See explanation about point mutations on [https://en.wikipedia.org/wiki/Point_mutation Wikipedia]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Please find answers [[SNP_calling_exercise_answers|here]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Congratulations you finished the exercise!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note: in these exercises and answers, sometimes piped the output of &amp;quot;bcftools view&amp;quot; into other programs, ideally you should use the flag:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-O,   --output-type &amp;lt;b|u|z|v&amp;gt;       b: compressed BCF, u: uncompressed BCF, z: compressed VCF, v: uncompressed VCF [v]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
and think about which one is appropriate for your situation whether you&#039;re storing data or piping to another program.&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
	<entry>
		<id>https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=146</id>
		<title>Unix pipes</title>
		<link rel="alternate" type="text/html" href="https://teaching.healthtech.dtu.dk/22126/index.php?title=Unix_pipes&amp;diff=146"/>
		<updated>2024-12-10T16:20:57Z</updated>

		<summary type="html">&lt;p&gt;Gabre: Created page with &amp;quot;Welcome! This small guide contains a lot of information and examples that will help you as you start learning Linux.  In addition to simple Linux commands, this tutorial also provides three Python scripts, that you can run and try out the concepts yourself.  # Basic Unix Commands and Concepts This is where your journey begins!  If you are new to Unix-based systems and also got used to Windows or MacOS, you really need a brief explanation of a few key commands and concept...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome! This small guide contains a lot of information and examples that will help you as you start learning Linux. &lt;br /&gt;
In addition to simple Linux commands, this tutorial also provides three Python scripts, that you can run and try out the concepts yourself.&lt;br /&gt;
&lt;br /&gt;
# Basic Unix Commands and Concepts&lt;br /&gt;
This is where your journey begins! &lt;br /&gt;
If you are new to Unix-based systems and also got used to Windows or MacOS, you really need a brief explanation of a few key commands and concepts. Vice versa, you will have a heart attack every time while writing some code, thinking hopefully you did not delete some important thing (based on experiences).&lt;br /&gt;
&lt;br /&gt;
## cd (Change Directory):&lt;br /&gt;
&lt;br /&gt;
The `cd` command is used to navigate between directories (folders) in a Unix-based system. &lt;br /&gt;
For example, if you are in a directory called home, and you want to move to a directory inside it called documents, you would type:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
cd documents&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
If you want to move to the parent directory, you can use:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
cd ..&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
If you ever want to return to your home directory, simply type:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
cd&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Also, you can combine some of them! If you want to move to the parent folder, and then go to another directory from there, you can simply write:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
cd ../directory_path&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
## ls (List Directory Contents)&lt;br /&gt;
&lt;br /&gt;
The `ls` command lists the contents of the current directory you are in. It shows all files and subdirectories within that directory. &lt;br /&gt;
For example, to see what files and directories are inside the current folder, type:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
ls&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
You can also add options to ls to view more details. For instance:&lt;br /&gt;
&lt;br /&gt;
- `ls -l` lists files with detailed information, such as file permissions, size, and modification dates.&lt;br /&gt;
- `ls -a` lists all files, including hidden ones (files that start with a dot .).&lt;br /&gt;
&lt;br /&gt;
## mkdir (Creating Directories)&lt;br /&gt;
&lt;br /&gt;
The `mkdir (make directory)` command is used for creating new directories (folders) within the Unix file system. Organizing files into directories helps maintain a structured and manageable file system., which is a good thing.&lt;br /&gt;
You can simply create directories from `your current directory` using `mkdir` like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
mkdir &#039;directory_path&#039;&lt;br /&gt;
```&lt;br /&gt;
For example, if you are in a directory named `my_directory` and want to create a directory named `my_new_directory`, you will write:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
mkdir my_new_directory&lt;br /&gt;
```&lt;br /&gt;
It will be created without notifying you. But you can check if the directory was created by using `ls`. The output of this command should be seen like this:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
*other folders or files&lt;br /&gt;
my_new_directory&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Checking it yourself is not bad, but it would be better if it would notify you when the directory is created. For that, you can use the flag `-v`! The &#039;v&#039; here means `verbose` and notifies you when the directory is created successfully, or vice versa. How does it notify? Outputting the success message to your terminal, since the terminal is where the standard output goes. What is standard output? We will talk about it later!&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
mkdir -v my_new_directory&lt;br /&gt;
```&lt;br /&gt;
This code now prints out the message that you created successfully the directory.&lt;br /&gt;
&lt;br /&gt;
Now imagine you need to create a folder, in a folder, which is in a folder. Creating all of them would not be that hard, but what if you need to create 20 folders like that? Instead of exhaustively doing that, you can use another flag, `-p`! `-p` flag will create parent directories as well, `__if they are not existing__`. You can achieve this like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
mkdir -p my_new_directory/my_another_new_directory/unix_tutorial&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code will create all directories if they do not exist. Also, you can combine the flags `-v` and `-p` to get notified at every creating step. &lt;br /&gt;
&lt;br /&gt;
You can ask yourself, why are we splitting all directories with `/` but not using it before the first directory? Normally you can use it, but having `/` at the very first position tells your system that you are trying to do something from the `root` directory. So if you add `/` before the `my_new_directory`, your system will create all folders not from your current location, but from the root directory. Yet you can use this if you want to create a directory rooting from different locations.&lt;br /&gt;
&lt;br /&gt;
## htop&lt;br /&gt;
&lt;br /&gt;
`htop` is an interactive and user-friendly process viewer for Unix systems. It provides a real-time, color-coded display of system processes, CPU usage, memory consumption, and more. If you are used to using Windows systems, `htop` is kinda similar to `Task Manager`.&lt;br /&gt;
You can open up `htop` by simply writing:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
htop&lt;br /&gt;
```&lt;br /&gt;
By writing that, you should get a tab like the following:&lt;br /&gt;
&lt;br /&gt;
![htop](https://github.com/user-attachments/assets/0ca69cd7-05e0-40d7-ba0f-8f539fda5b91)&lt;br /&gt;
&lt;br /&gt;
The best thing (for me) `htop` providing is the `with mouse navigating`. You can click the buttons on green line and access CPU-Usage, Memory-Usage and so on.&lt;br /&gt;
&lt;br /&gt;
## time&lt;br /&gt;
&lt;br /&gt;
`time` is a tiny command that helps measure the execution time of a command or script. It gives out three different measurements, which are:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real: Total elapsed time starting with input and end of the task.&lt;br /&gt;
user: CPU time spent in user mode. This is the runtime of your code.&lt;br /&gt;
sys: CPU time spent in kernel mode. This is the writing to file, reading from file, and such things (file descriptors or pipes).&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
# stdout, stdin and stderr&lt;br /&gt;
&lt;br /&gt;
## stdout (Standard Output)&lt;br /&gt;
&lt;br /&gt;
`stdout` stands for &amp;quot;standard output&amp;quot;, where a program sends its regular output. &lt;br /&gt;
In most cases, this is your terminal screen. For example, when a command or program runs successfully, the result is displayed on `stdout`, i.e. your terminal.&lt;br /&gt;
You can redirect this output to a file if you don’t want it displayed on the screen. &lt;br /&gt;
&lt;br /&gt;
Lets say, you have a program, `hello_world.py`, that simply writes out &amp;quot;Hello World!&amp;quot; to the terminal, looking like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this command in Linux by writing `python3 hello_world.py` you will see the output `Hello World!` in your terminal. &lt;br /&gt;
&lt;br /&gt;
Let&#039;s break down this code together. First, we need to write `python3` in unix-based systems to call python files successfully. Then, we need to say which file would be called. In this case, the name of our little program is `hello_world.py`. When you give only these two as a command, it will normally write out `Hello World!` to the terminal.&lt;br /&gt;
&lt;br /&gt;
Cool, right? But what if you want to print out this output to a text file named `greeting.txt`? The first way to achieve this, you could change the program itself like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Redirect stdout to a file&lt;br /&gt;
with open(&amp;quot;greeting.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:&lt;br /&gt;
    sys.stdout = file&lt;br /&gt;
    print(&amp;quot;Hello World!&amp;quot;)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
And then, `python3 hello_world.py` would create `greeting.txt`, and append `Hello World!` in it. When you achieve this, it still writes it out to the `stdout` but the directory of `stdout` would be changed. Yet it works for us, it kinda seems a bit exhaustive. &lt;br /&gt;
&lt;br /&gt;
The second way, and a bit easier way is using directly `file descriptors` of Linux. Using file descriptors is a way to manipulate the outputs, errors, and inputs of programs. Using the very first version of `hello_world.py` and file descriptors, you can achieve it like:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; greeting.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The `&amp;gt;` operator here, is one of the basic `file descriptors` in Linux. Using it like that, you will redirect the `output` of the program into a file. In detail, we will talk about it in next chapters.&lt;br /&gt;
&lt;br /&gt;
There may also be a situation where you want to delete the output of the program. You can do this again using file descriptors. The directory named ‘/dev/null’ is a special directory and acts like a black hole, so to speak. Everything you send there will be lost. Suppose we don&#039;t want to see the output of `hello_world.py`. We can achieve this as follows: &lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
python3 hello_world.py &amp;gt; /dev/null&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
## stdin (Standard Input)&lt;br /&gt;
&lt;br /&gt;
`stdin` stands for &amp;quot;standard input&amp;quot; and is where a program receives its input. By default, this is the keyboard, but it can also come from a file or the output of another command. &lt;br /&gt;
For example, if you run a command and are prompted to type something, that input is coming from `stdin`.&lt;br /&gt;
&lt;br /&gt;
Imagine our `hello_world.py` also says our name! As the program can not know your name, &amp;quot;legally&amp;quot;, you need to specify this. You can give your name like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py ozgur&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Aaaaand it won&#039;t work. It is because normally, your python code can not understand if an `argument` exists in your command line. The library named `argparse` in python helps you to take inputs better from the command line! When you set up argparse and modify your code correctly, it will take input from the command line and process it.&lt;br /&gt;
&lt;br /&gt;
We can modify our little code like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    parser = argparse.ArgumentParser(description=&amp;quot;Greeting Message&amp;quot;)&lt;br /&gt;
    parser.add_argument(&#039;name&#039;, nargs=&#039;?&#039;, help=&#039;Your name to greet correctly&#039;)&lt;br /&gt;
    args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
    print(f&amp;quot;Hello World! {args.name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Well, that&#039;s a huge modification at all. &lt;br /&gt;
&lt;br /&gt;
Here what we call &#039;parser&#039; is our python class. We add an argument to this class and name it &#039;name&#039;. Then we use parser.parse_args() to get the arguments correctly. This will allow us to keep each argument by flags. So when you type your name in the argument point flagged &#039;name&#039;, you can call it as name.`yourname`. Now, if you call the code like:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py ozgur&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
You will get:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! ozgur&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Even if it doesn&#039;t make sense, we were able to get our output right, that&#039;s something.&lt;br /&gt;
&lt;br /&gt;
Now imagine you have two python codes. One of them picks a random name and the second one prints Hello World [name] with the chosen name (our little programme). You can run your first code, see what it outputs, and use the second code by writing the output of the first code. It won&#039;t bother you since you are taking only one name at a time, but imagine inputting 50 random names. To hinder this hard work, you can use `pipes!` Pipe is a kind of operator in unix-based systems, that helps you connect `stdout` and `stdin` of different codes. Also when you want to use the `pipe` operator, you do not need `argparse`. By using file descriptors, or pipes, you change the type of the input into a file, so you need to process it like a file.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s name our first code `random_name_generator.py`:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
names = [&lt;br /&gt;
    &amp;quot;Anders&amp;quot;, &amp;quot;Niels&amp;quot;, &amp;quot;Jens&amp;quot;, &amp;quot;Poul&amp;quot;, &amp;quot;Lars&amp;quot;, &amp;quot;Morten&amp;quot;, &amp;quot;Søren&amp;quot;, &amp;quot;Thomas&amp;quot;, &amp;quot;Peter&amp;quot;, &amp;quot;Martin&amp;quot;,&lt;br /&gt;
    &amp;quot;Henrik&amp;quot;, &amp;quot;Jesper&amp;quot;, &amp;quot;Frederik&amp;quot;, &amp;quot;Kasper&amp;quot;, &amp;quot;Rasmus&amp;quot;, &amp;quot;Svend&amp;quot;, &amp;quot;Jacob&amp;quot;, &amp;quot;Simon&amp;quot;, &amp;quot;Mikkel&amp;quot;, &amp;quot;Christian&amp;quot;,&lt;br /&gt;
    &amp;quot;Brian&amp;quot;, &amp;quot;Steffen&amp;quot;, &amp;quot;Jonas&amp;quot;, &amp;quot;Mark&amp;quot;, &amp;quot;Daniel&amp;quot;, &amp;quot;Carsten&amp;quot;, &amp;quot;Torben&amp;quot;, &amp;quot;Bent&amp;quot;, &amp;quot;Erik&amp;quot;, &amp;quot;Michael&amp;quot;,&lt;br /&gt;
    &amp;quot;Viggo&amp;quot;, &amp;quot;Oskar&amp;quot;, &amp;quot;Emil&amp;quot;, &amp;quot;Victor&amp;quot;, &amp;quot;Alexander&amp;quot;, &amp;quot;Sebastian&amp;quot;, &amp;quot;Oliver&amp;quot;, &amp;quot;William&amp;quot;, &amp;quot;Noah&amp;quot;, &amp;quot;Lasse&amp;quot;,&lt;br /&gt;
    &amp;quot;Mads&amp;quot;, &amp;quot;Bjørn&amp;quot;, &amp;quot;Leif&amp;quot;, &amp;quot;Gunnar&amp;quot;, &amp;quot;Elias&amp;quot;, &amp;quot;August&amp;quot;, &amp;quot;Aksel&amp;quot;, &amp;quot;Finn&amp;quot;, &amp;quot;Ebbe&amp;quot;, &amp;quot;Vladimir&amp;quot;,&lt;br /&gt;
    &amp;quot;Anne&amp;quot;, &amp;quot;Karen&amp;quot;, &amp;quot;Pia&amp;quot;, &amp;quot;Mette&amp;quot;, &amp;quot;Lise&amp;quot;, &amp;quot;Hanne&amp;quot;, &amp;quot;Rikke&amp;quot;, &amp;quot;Sofie&amp;quot;, &amp;quot;Camilla&amp;quot;, &amp;quot;Maria&amp;quot;,&lt;br /&gt;
    &amp;quot;Julie&amp;quot;, &amp;quot;Christine&amp;quot;, &amp;quot;Birthe&amp;quot;, &amp;quot;Tine&amp;quot;, &amp;quot;Kirsten&amp;quot;, &amp;quot;Ingrid&amp;quot;, &amp;quot;Line&amp;quot;, &amp;quot;Trine&amp;quot;, &amp;quot;Kristine&amp;quot;, &amp;quot;Mia&amp;quot;,&lt;br /&gt;
    &amp;quot;Cecilie&amp;quot;, &amp;quot;Charlotte&amp;quot;, &amp;quot;Emma&amp;quot;, &amp;quot;Ida&amp;quot;, &amp;quot;Nadia&amp;quot;, &amp;quot;Sanne&amp;quot;, &amp;quot;Sara&amp;quot;, &amp;quot;Eva&amp;quot;, &amp;quot;Helene&amp;quot;, &amp;quot;Nanna&amp;quot;,&lt;br /&gt;
    &amp;quot;Maja&amp;quot;, &amp;quot;Lærke&amp;quot;, &amp;quot;Molly&amp;quot;, &amp;quot;Stine&amp;quot;, &amp;quot;Emilie&amp;quot;, &amp;quot;Amalie&amp;quot;, &amp;quot;Signe&amp;quot;, &amp;quot;Freja&amp;quot;, &amp;quot;Isabella&amp;quot;, &amp;quot;Tuva&amp;quot;,&lt;br /&gt;
    &amp;quot;Viktoria&amp;quot;, &amp;quot;Ane&amp;quot;, &amp;quot;Dorte&amp;quot;, &amp;quot;Laura&amp;quot;, &amp;quot;Asta&amp;quot;, &amp;quot;Marie&amp;quot;, &amp;quot;Clara&amp;quot;, &amp;quot;Sofia&amp;quot;, &amp;quot;Filippa&amp;quot;, &amp;quot;Ella&amp;quot;,&lt;br /&gt;
    &amp;quot;Alex&amp;quot;, &amp;quot;Robin&amp;quot;, &amp;quot;Kim&amp;quot;, &amp;quot;Sam&amp;quot;, &amp;quot;Alexis&amp;quot;, &amp;quot;Charlie&amp;quot;, &amp;quot;Taylor&amp;quot;, &amp;quot;Jamie&amp;quot;, &amp;quot;Morgan&amp;quot;, &amp;quot;Riley&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
# Select 10 random names without replacement&lt;br /&gt;
random_names = random.sample(danish_names, 10)&lt;br /&gt;
&lt;br /&gt;
# Print each name on a separate line&lt;br /&gt;
for name in random_names:&lt;br /&gt;
    print(name)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
And after a little adjustments, our `hello_world.py`:&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping lines&lt;br /&gt;
        if name:  # For every name&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
You can achieve the given task using pipes like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_name_generator.py | python3 hello_world.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
or with file descriptors:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_name_generator.py &amp;gt; names.txt&lt;br /&gt;
python3 hello_world.py &amp;lt; names.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Both work perfectly, but notice how easier to use `pipes` for this type of task, compared to file descriptors.&lt;br /&gt;
&lt;br /&gt;
## stderr (Standard Error)&lt;br /&gt;
&lt;br /&gt;
`stderr` stands for &amp;quot;standard error&amp;quot; and is used by programs to send error messages or diagnostics. &lt;br /&gt;
This is also shown on your terminal screen by default, but it is separate from `stdout`. Reading both of them on your terminal would be hard to distinguish them, so redirecting one of them would be better in general.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s say we want to print a status message for the `hello_world.py`. After every line is written out as stdout, it should provide the status message, `Name greeted: name`. We can directly print it out with print function like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Reading names&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()  # Stripping&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
When you run this code, it will output something like that:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Hello World! Maria&lt;br /&gt;
Name greeted: Maria&lt;br /&gt;
Hello World: Anders&lt;br /&gt;
Name greeted: Anders&lt;br /&gt;
...&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
It works, but it is not something we want to achieve. First, the `status message` is still going to `stdout`. &lt;br /&gt;
&lt;br /&gt;
If you change the stdout location using the file descriptor, all messages will still go to the same place. So first we need to define the status message as `stderr` and then change the `output location of stderr`.&lt;br /&gt;
&lt;br /&gt;
We can achieve the defining `stderr` like this:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    for line in sys.stdin:&lt;br /&gt;
        name = line.strip()&lt;br /&gt;
        if name:&lt;br /&gt;
            print(f&amp;quot;Hello World! {name}&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Name greeted: {name}&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
`file` is an argument of `print` function in python, which specifies where the output goes. If you give a specific text file to that argument, it prints out there. The default value of it is `sys.stdout`, so basically `stdout`. You can change it by specifying that argument as `file=sys.stderr`. &lt;br /&gt;
&lt;br /&gt;
Now we want to redirect this status message into a file named `status.txt`. As we do it before, we can use `file descriptors`! Let&#039;s try it like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py &amp;gt; status.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Did not work right? That&#039;s because the `&amp;gt;` operator redirects only `stdout`. If we want to redirect `stderr`, we specify this with `2&amp;gt;`! But why, we did not use some number for redirecting `stdout`? All `stdout, stderr, and stdin` have values for specifying.&lt;br /&gt;
&lt;br /&gt;
- Standard Input (stdin): File descriptor 0&lt;br /&gt;
- Standard Output (stdout): File descriptor 1&lt;br /&gt;
- Standard Error (stderr): File descriptor 2&lt;br /&gt;
&lt;br /&gt;
But the default one is `stdout`, so you do not need to define it explicitly. &lt;br /&gt;
&lt;br /&gt;
Based on this information, we can redirect our status message into `status.txt` with following command:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 hello_world.py 2&amp;gt; status.txt &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
That&#039;s the end of this chapter. Next on, we will talk about a real-world implementation of all the concepts above.&lt;br /&gt;
&lt;br /&gt;
# Real World Example&lt;br /&gt;
&lt;br /&gt;
Welcome! This part of the tutorial provides a real-world example where you can use what you have learned above. All of the code examples below can be found in this GitHub repository. So let&#039;s get started!&lt;br /&gt;
&lt;br /&gt;
# Random Integer Generator&lt;br /&gt;
&lt;br /&gt;
Let&#039;s see the script first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
import random as r&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;This program generates random integers within a given interval.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;num_of_nums&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;n&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            nargs=&amp;quot;?&amp;quot;,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;number of generated numbers (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--min&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;min&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=10,&lt;br /&gt;
            help=&amp;quot;minimum value of the interval (default: 10)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--max&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;max&amp;quot;,&lt;br /&gt;
            type=int,&lt;br /&gt;
            default=100,&lt;br /&gt;
            help=&amp;quot;maximum value of the interval (default: 100)&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
            &amp;quot;--output&amp;quot;, &amp;quot;-o&amp;quot;,&lt;br /&gt;
            metavar=&amp;quot;FILE&amp;quot;,&lt;br /&gt;
            type=str,&lt;br /&gt;
            default=&amp;quot;random_numbers.txt&amp;quot;,&lt;br /&gt;
            help=&amp;quot;output file to write the numbers (default: random_numbers.txt)&amp;quot;)&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Main function to run the random integer generator and measure its runtime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # Record the start time&lt;br /&gt;
    start_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Run the random integer generator&lt;br /&gt;
    random_int_generator(args.num_of_nums, args.min, args.max)&lt;br /&gt;
&lt;br /&gt;
    # Record the end time&lt;br /&gt;
    end_time = time.perf_counter()&lt;br /&gt;
&lt;br /&gt;
    # Calculate the runtime&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Print the runtime to stderr to keep it separate from the generated numbers&lt;br /&gt;
    print(f&amp;quot;The runtime of the random integer generator is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `n` (positional, optional): The number of random integers to generate. Defaults to 100 if not specified.&lt;br /&gt;
- `--min` (optional): The minimum value of the interval. Defaults to 10.&lt;br /&gt;
- `--max` (optional): The maximum value of the interval. Defaults to 100.&lt;br /&gt;
- `--output` (optional): The output file of random numbers. Defaults to &#039;random_numbers.txt&#039;&lt;br /&gt;
Ensure that the `min` value is less than or equal to the `max` value to avoid errors.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The script is designed to generate random integers within a specified interval. Also, this script can be executed from the command line with optional arguments to specify the number of integers to generate and the range of values. The script itself returns none since the generated numbers are written directly to a file named `outputs.txt`. At this point, you should be saying: `But wait! We did learn, that connecting scripts with pipes does not require creating files!` You are correct. We really do not need that output file, since we will be connecting them directly. To achieve this, let&#039;s change the part:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers = 100, min_interval = 10, max_interval = 100):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to outputs.txt.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(&amp;quot;outputs.txt&amp;quot;, &amp;quot;w&amp;quot;) as file:  # Open the file for writing&lt;br /&gt;
        for _ in range(number_of_numbers):&lt;br /&gt;
            num = r.randint(min_interval, max_interval)&lt;br /&gt;
            file.write(f&amp;quot;{num}\n&amp;quot;)  # Write each number to the file, one per line&lt;br /&gt;
```&lt;br /&gt;
into this:&lt;br /&gt;
```python&lt;br /&gt;
def random_int_generator(number_of_numbers, min_interval, max_interval):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Generates random integers within a specified interval and writes them to stdout.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    for _ in range(number_of_numbers):&lt;br /&gt;
        num = r.randint(min_interval, max_interval)&lt;br /&gt;
        print(num, file=sys.stdout)&lt;br /&gt;
```&lt;br /&gt;
Voilá! Now it prints out everything into stdout, like we discussed in the previous section. &lt;br /&gt;
&lt;br /&gt;
To generate 50 random integers between 1 and 50, you would run this code as:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_int_generator.py 50 --min 1 --max 50&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This code also provides the `runtime`, which is printed out directly to the `stderr`. By measuring the runtime, you can evaluate how quickly the program generates the desired number of random integers within the specified interval. This information is crucial for optimizing the code, especially when scaling up to generate larger datasets or integrating the generator into larger applications where performance may impact overall system efficiency. And while this process is ongoing, you can check memory or CPU usage by using `htop`, as we talked about in the previous section. &lt;br /&gt;
&lt;br /&gt;
We will check the runtimes after the introduction of all three scripts :).&lt;br /&gt;
&lt;br /&gt;
# Prime Checker (Naive)&lt;br /&gt;
The code for the naive approach seems like this:&lt;br /&gt;
```python&lt;br /&gt;
import math&lt;br /&gt;
import argparse&lt;br /&gt;
import time&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
parser = argparse.ArgumentParser(description=&amp;quot;Prime Number Checker. This program checks if the input numbers are prime and writes the primes to an output file.&amp;quot;)&lt;br /&gt;
parser.add_argument(&lt;br /&gt;
    &#039;input_file&#039;,&lt;br /&gt;
    nargs=&#039;?&#039;,&lt;br /&gt;
    type=str,&lt;br /&gt;
    default=&#039;-&#039;,&lt;br /&gt;
    help=&#039;Path to the input file containing numbers to check. Use &amp;quot;-&amp;quot; or omit to read from stdin.&#039;&lt;br /&gt;
    )&lt;br /&gt;
args = parser.parse_args()&lt;br /&gt;
&lt;br /&gt;
def is_prime(num):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check if a number is prime.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if num &amp;lt;= 1:&lt;br /&gt;
        return False&lt;br /&gt;
    if num &amp;lt;= 3:&lt;br /&gt;
        return True&lt;br /&gt;
    if num % 2 == 0 or num % 3 == 0:&lt;br /&gt;
        return False&lt;br /&gt;
    sqrt_num = int(math.sqrt(num)) + 1&lt;br /&gt;
    for i in range(5, sqrt_num, 6):&lt;br /&gt;
        if num % i == 0 or num % (i + 2) == 0:&lt;br /&gt;
            return False&lt;br /&gt;
    return True&lt;br /&gt;
&lt;br /&gt;
def prime_checker(numbers):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Check which numbers are prime and return them as a list.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    primes = list(filter(is_prime, numbers))&lt;br /&gt;
    return primes&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    # Determine the input source: file or stdin&lt;br /&gt;
    if args.input_file == &#039;-&#039; or args.input_file == &#039;&#039;:&lt;br /&gt;
        input_source = sys.stdin&lt;br /&gt;
    else:&lt;br /&gt;
        input_source = open(args.input_file, &#039;r&#039;)&lt;br /&gt;
&lt;br /&gt;
    # Read numbers from the input source&lt;br /&gt;
    with input_source:&lt;br /&gt;
        input_data = input_source.read().strip().split()&lt;br /&gt;
        numbers = list(map(int, input_data))&lt;br /&gt;
&lt;br /&gt;
    # Measure runtime&lt;br /&gt;
    start_time = time.time()&lt;br /&gt;
    primes = prime_checker(numbers)&lt;br /&gt;
    end_time = time.time()&lt;br /&gt;
    runtime = end_time - start_time&lt;br /&gt;
&lt;br /&gt;
    # Write primes to the stdout&lt;br /&gt;
    if primes:&lt;br /&gt;
        print(&amp;quot;\n&amp;quot;.join(map(str, primes)), file=sys.stdout)&lt;br /&gt;
&lt;br /&gt;
    # Print runtime to stderr&lt;br /&gt;
    print(f&amp;quot;The runtime of the prime checker is {runtime:.6f} seconds&amp;quot;, file=sys.stderr)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
where,&lt;br /&gt;
```&lt;br /&gt;
Arguments (or flags) are:&lt;br /&gt;
- `input file` (positional, optional): The file consisting random integers. If not given, it will try to read from stdin.&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
This prime checker script is designed to determine if numbers provided via standard input (`stdin`) or through a file, are prime. &lt;br /&gt;
It outputs the prime numbers to standard output and into a file, and logs the runtime of the operation directly to the stderr.&lt;br /&gt;
It returns prime numbers line by line.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s start talking about what does the `naive approach.` The `naive approach`, is a function that efficiently determines whether a given number `num` is prime. It first excludes numbers less than or equal to 1 and directly identifies 2 and 3 as prime. It then eliminates any even numbers and multiples of 3 to reduce unnecessary checks. For numbers greater than 3, the function iterates from 5 up to the square root of num, checking divisibility in steps of 6. This approach leverages the fact that all primes greater than 3 are of the form `6k ± 1`, thereby minimizing the number of iterations and enhancing performance compared to the naive method of checking all numbers up to `num - 1`. If no divisors are found, the function concludes that num is prime.&lt;br /&gt;
&lt;br /&gt;
Since this script needs a list of integers, which are line by line (what a coincidence), you can take these integers from `random_int_generator.py!` Instead of exhaustively having these numbers and feeding them into `prime_checker.py` separately, we can use the brand new thing we learned, `pipes`!&lt;br /&gt;
&lt;br /&gt;
You can pipe both scripts like this:&lt;br /&gt;
```bash&lt;br /&gt;
python3 random_integer_generator.py | python prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
As we specified earlier, the random integer generator generates 100 numbers between 10 and 100, so our prime checker would be fed with them. It will then print out only `prime ones`. That means, the original output of `random_int_generator.py` would be omitted since it has been redirected to the `prime_checker.py`. Also this prime checker code provides the runtime to the user, for assessing the performance of this code.&lt;br /&gt;
&lt;br /&gt;
# RSA Checker&lt;br /&gt;
Here comes the code first:&lt;br /&gt;
&lt;br /&gt;
```python&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def rsa_key_checker(p, q, e):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Compute the RSA key pair given primes p and q and a public exponent e.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    modulus = p * q&lt;br /&gt;
    phi_n = (p - 1) * (q - 1)&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        private_exponent = pow(e, -1, phi_n)  # Calculate private exponent d&lt;br /&gt;
    except ValueError:&lt;br /&gt;
        return False, &amp;quot;No modular inverse exists for e and phi(n)&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    # Test the RSA encryption/decryption cycle&lt;br /&gt;
    test_message = 42&lt;br /&gt;
    encrypted_message = pow(test_message, e, modulus)&lt;br /&gt;
    decrypted_message = pow(encrypted_message, private_exponent, modulus)&lt;br /&gt;
    &lt;br /&gt;
    if test_message != decrypted_message:&lt;br /&gt;
        return False, &amp;quot;Encryption/Decryption failed&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    return True, f&amp;quot;Valid RSA key pair. Modulus = {modulus}, Public Exponent = {e}, Private Exponent = {private_exponent}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_next_prime(file):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Read the next prime number from a file.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    line = file.readline()&lt;br /&gt;
    if line:&lt;br /&gt;
        return int(line.strip())&lt;br /&gt;
    return None&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    if len(sys.argv) != 3:&lt;br /&gt;
        print(&amp;quot;Usage: python RSAChecker.py [file_with_primes_1] [file_with_primes_2]&amp;quot;)&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    primes_file_1 = sys.argv[1]&lt;br /&gt;
    primes_file_2 = sys.argv[2]&lt;br /&gt;
&lt;br /&gt;
    # Common public exponent&lt;br /&gt;
    e = 65537&lt;br /&gt;
&lt;br /&gt;
    # Open both files&lt;br /&gt;
    with open(primes_file_1, &amp;quot;r&amp;quot;) as file1, open(primes_file_2, &amp;quot;r&amp;quot;) as file2:&lt;br /&gt;
        while True:&lt;br /&gt;
            p = read_next_prime(file1)&lt;br /&gt;
            q = read_next_prime(file2)&lt;br /&gt;
            &lt;br /&gt;
            if p is None or q is None:&lt;br /&gt;
                if p is None and q is None:&lt;br /&gt;
                    break  # Both files are fully processed&lt;br /&gt;
                # Handle cases where one file has fewer lines&lt;br /&gt;
                if p is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 1 has fewer lines than File 2. Stopping.&amp;quot;)&lt;br /&gt;
                if q is None:&lt;br /&gt;
                    print(&amp;quot;Warning: File 2 has fewer lines than File 1. Stopping.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
            # Compute the RSA key pair without checking if p and q are prime&lt;br /&gt;
            valid, message = rsa_key_checker(p, q, e)&lt;br /&gt;
            if valid:&lt;br /&gt;
                print(message)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The RSAchecker.py script is designed to generate RSA key pairs from two lists of prime numbers. &lt;br /&gt;
It reads prime numbers from two files, computes the RSA key pair for each pair of primes, and checks if the encryption and decryption process is successful. If you want to learn about it further, you can find information about RSA encryption further on the internet.&lt;br /&gt;
&lt;br /&gt;
To use this script, you need to provide two files containing prime numbers, one is so-called `public keys`, and the other one is `private keys`. Each file should have one prime number per line. The script will read these files, compute RSA key pairs, and verify their validity.&lt;br /&gt;
&lt;br /&gt;
The correct way to use this script follows:&lt;br /&gt;
python RSAchecker.py [file_with_primes_1] [file_with_primes_2]&lt;br /&gt;
&lt;br /&gt;
But since we do not have the prime numbers in files, we need to utilize `file descriptors`! A way to use two file descriptors at the same time is by bundling commands together with parenthesis. It will bundle the codes together and redirects the output of all code inside the parentheses. A little confusing, right? Let&#039;s break it down, using an example:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
python3 RSAchecker.py &amp;lt;(python random_integer_generator.py | python prime_checker.py) &amp;lt;(python random_integer_generator.py | python prime_checker.py)&lt;br /&gt;
```&lt;br /&gt;
We knew the part inside the parentheses, it outputs a list of prime numbers. Now, we do it two times since we need a pair of prime numbers. We bundled the parts that output prime numbers and redirected them to the `RSAchecker.py`. `&amp;lt;` indicates that the input goes into the file, so that is the reverse of what we did in the previous section. &lt;br /&gt;
&lt;br /&gt;
And voila! It worked perfectly, and we have valid prime number pairs for encryption. &lt;br /&gt;
&lt;br /&gt;
Congrats! Your encryption works!&lt;br /&gt;
&lt;br /&gt;
# Benchmarking&lt;br /&gt;
&lt;br /&gt;
Love to see all codes in action, but checking if they are working optimized is another concern since we need everything (ideally) low-cost at the means of time, calculations, and such. So we need to benchmark our pipeline to see if some code bottlenecks or raises errors during the pipeline. For this benchmarking, we are going to use the `time` function of Linux (see Linux Concepts Section, if you already forgot :D.) Let&#039;s start building our pipeline!&lt;br /&gt;
&lt;br /&gt;
# Time Efficiency Benchmarking&lt;br /&gt;
&lt;br /&gt;
## Random Integer Generator and Prime Checker&lt;br /&gt;
&lt;br /&gt;
Based on our knowledge from the previous section, we know that we can achieve this pipeline with various methods, like using intermediate files, file descriptors, or pipes. So when we need to pick any of them, the concern is cost efficiency, and in this case, it is time efficiency. Let&#039;s try every method and check if it really changes that much. We are going to generate 50.000.000 numbers in every test, which are between 100 and 1.000.000. All tests are undergone with 6GB RAM and 2GB Swap Memory.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We will, for testing intermediate files, generate a file consists all random integers and feed `prime checker` with them. In order to achieve that, we will check them separately and add up later. We will use the code:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 &amp;gt; random_integers.txt&lt;br /&gt;
time python3 prime_checker.py random_integers.txt &amp;gt; prime_list_first.txt&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The runtime of both are, respectively:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m44.270s&lt;br /&gt;
user    0m42.046s&lt;br /&gt;
sys     0m2.200s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    2m39.985s&lt;br /&gt;
user    2m6.337s&lt;br /&gt;
sys     0m25.831s&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Which makes total of nearly 3 minutes and 30 seconds, `without coding time.` Please note that the prime checker works way much slower than the random integer generator.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes&lt;br /&gt;
&lt;br /&gt;
Let&#039;s pipe them together! We will use the code below:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 50000000 --min 100 --max 1000000 | python3 prime_checker.py&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
The total runtime of this code is:&lt;br /&gt;
```&lt;br /&gt;
real    2m41.284s&lt;br /&gt;
user    2m21.816s&lt;br /&gt;
sys     0m15.455s&lt;br /&gt;
```&lt;br /&gt;
It made a difference, yes? A minute down seems not that big but imagine much bigger tasks. We always prefer lower time consumptions with also `lower coding times.`&lt;br /&gt;
&lt;br /&gt;
### Using File Descriptors&lt;br /&gt;
&lt;br /&gt;
The file descriptors method is the last method to benchmark between the random integer generator and prime checker. After this, we will be going to connect all three scripts and find the best-est method of all time! Connecting with file descriptors these two scripts would be achieved like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 prime_checker_naive_approach.py &amp;gt; primes.txt &amp;lt;(python3 random_int_generator.py 50000000 --min 100 --max 1000000)&lt;br /&gt;
```&lt;br /&gt;
and the runtime:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    2m50.221s&lt;br /&gt;
user    2m31.008s&lt;br /&gt;
sys     0m12.328s&lt;br /&gt;
```&lt;br /&gt;
It made no observable difference between pipes and file descriptors, but surely they are much faster than using intermediate files. So we are going to use one of the faster ones in RSA benchmarking.&lt;br /&gt;
&lt;br /&gt;
## RSA Checker and Others&lt;br /&gt;
&lt;br /&gt;
We know by now, which methods are faster, so we will stick to it. Yet, let&#039;s try and see one more time the time difference using a more automated method and exhaustively transporting files here and there, between scripts.&lt;br /&gt;
Let&#039;s take firstly the long road.&lt;br /&gt;
&lt;br /&gt;
And the other thing is, that we will generate only 5.000.000 of integers here, we will talk about it in short.&lt;br /&gt;
&lt;br /&gt;
### Using Intermediate Files&lt;br /&gt;
&lt;br /&gt;
We can achieve it with the following codes:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes.txt&lt;br /&gt;
time python3 random_int_generator.py 5000000 --min 100 --max 1000000 | python3 prime_checker_naive_approach.py &amp;gt; primes2.txt&lt;br /&gt;
time python3 RSAchecker.py primes.txt primes2.txt &amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
After running them all, the runtimes would look like:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m12.585s&lt;br /&gt;
user    0m10.159s&lt;br /&gt;
sys     0m2.642s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m10.612s&lt;br /&gt;
user    0m10.117s&lt;br /&gt;
sys     0m0.670s&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
real    0m3.912s&lt;br /&gt;
user    0m3.486s&lt;br /&gt;
sys     0m0.411s&lt;br /&gt;
```&lt;br /&gt;
It took nearly 27 seconds to resolve all three codes, with 3 files taking nearly 60MB of space. Now let&#039;s try it with the much faster method.&lt;br /&gt;
&lt;br /&gt;
### Using Pipes and File Descriptors Together&lt;br /&gt;
&lt;br /&gt;
We will modify the code we used in the previous section while introducing RSAchecker. The code will look like this:&lt;br /&gt;
&lt;br /&gt;
```bash&lt;br /&gt;
time python3 RSAcheckerNEW.py &amp;gt; valid_pairs.txt&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;lt;(python random_int_generator.py 50000000 --min 100 --max 1000000 | python prime_checker_naive_approach.py)&lt;br /&gt;
&amp;gt; valid_pairs.txt&lt;br /&gt;
```&lt;br /&gt;
aaaaand here comes the runtime!!!:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
real    0m15.262s&lt;br /&gt;
user    0m3.468s&lt;br /&gt;
sys     0m0.480s&lt;br /&gt;
```&lt;br /&gt;
Really a huge improvement. In the means of time, using much more automated architectures and omitting files make a huge difference.&lt;br /&gt;
&lt;br /&gt;
But let&#039;s talk about why we did not use fifty million integers as we did earlier? Yeah, to be honest, 6GB RAM can not handle processing that much of integers. That leads us to the second important thing, the `computational load.` The main concern at this point is, which script causes that overload? Let&#039;s find out that together!&lt;br /&gt;
&lt;br /&gt;
## Computational Load Benchmarking with `htop`&lt;br /&gt;
&lt;br /&gt;
As we talked about it in the Linux Concepts section, `htop` helps us to find out the computational load. We need to open a `htop` screen.&lt;br /&gt;
I will provide here a couple of `htop` screenshots, let&#039;s compare them.&lt;br /&gt;
&lt;br /&gt;
The first one is taken during the random integer generation.&lt;br /&gt;
![during random int](https://github.com/user-attachments/assets/949ae9e7-6c94-42a9-94a5-1f9239a1aaf5)&lt;br /&gt;
The maximum percentage usage of CPU and Memory is nearly 2.7% here, not much, not to be concerned about. We can see that the random integer generator works rather optimized. At least, it does not bring the computational load we are talking about here.&lt;br /&gt;
&lt;br /&gt;
The second screenshot have been taken right after the random integer generation.&lt;br /&gt;
![after random int](https://github.com/user-attachments/assets/4b979224-93f0-484f-97f5-b68ac13e09c4)&lt;br /&gt;
Note that the both memory and CPU usage went sharply up, and caused some absurd numbers, like 101% usage of CPU. Initialization may caused that, but the program works still. &lt;br /&gt;
&lt;br /&gt;
But after that, the third one was caught during the prime checker:&lt;br /&gt;
![during prime checker](https://github.com/user-attachments/assets/8e00ebd4-89ec-4a13-a540-e359ec9cfec3)&lt;br /&gt;
It seems like they not using all % of both CPU and Memory, the current usage says different things. As we can see, all of the memory and swap memory filled up. That&#039;s exactly when the process has been killed also. The program can not move to the RSA checking part, because everything has been killed in this part and stopped already. At this point, we should ask ourselves how to optimize or maybe bypass this step to get a more efficient pipeline. Also as we said earlier, we will provide another prime checking algorithms besides the naive one, you can check yourself and find out which one is the better :).&lt;br /&gt;
&lt;br /&gt;
# Thanks for the attention! See you in another tutorial!&lt;br /&gt;
Written by Özgür Yolcu&lt;br /&gt;
&lt;br /&gt;
Instructed by Gabriel Renaud&lt;/div&gt;</summary>
		<author><name>Gabre</name></author>
	</entry>
</feed>