├── LICENSE
├── README.txt
├── dfg_proposal_en.cls
├── dfg_proposal_en.tex
└── scientific_programming.ipynb
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Karl Kirschner
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | Latex version of DFG's Basic Module in English.
2 |
3 | Original and up-to-date (non-Latex) forms are found on the DFG website: https://www.dfg.de/foerderung/formulare_merkblaetter
4 |
5 | ## For version of LaTeX2e: latex '\typeout{\fmtversion}\stop' | grep LaTeX2e
6 |
7 | Latex version requirement: \NeedsTeXFormat{LaTeX2e}[2017/04/15]
8 |
9 | Requires the following Latex libraries (see dfg_proposal_en.cls):
10 |
11 | Formatting:
12 | 1. \RequirePackage[utf8]{inputenc}
13 | 2. \RequirePackage[english]{babel}
14 | 3. \RequirePackage{anyfontsize}
15 | 4. \RequirePackage{microtype}
16 | 5. \RequirePackage{geometry}
17 | 6. \geometry{a4paper, left=1.7cm, right=1.8cm, top=2.0cm, bottom=1.5cm, headheight=1.0cm}
18 | 7. \RequirePackage{fancyhdr}
19 | 8. \RequirePackage{indentfirst}
20 | 9. \RequirePackage[official]{eurosym}
21 | 10. \RequirePackage[dvipsnames]{xcolor}
22 | \definecolor{dfgblue}{RGB}{0, 82, 158}
23 |
24 | Figures:
25 | 11. \RequirePackage{graphicx}
26 | 12. \RequirePackage[font=normal,labelfont=bf]{caption}
27 | 13. \RequirePackage{subfig}
28 | 14. \RequirePackage{wrapfig}
29 |
30 | Tables:
31 | 15. \RequirePackage{threeparttable}
32 | 16. \RequirePackage{booktabs}
33 | 17. \RequirePackage[labelfont=bf]{caption}
34 | 18. \RequirePackage{colortbl}
35 |
36 | Math:
37 | 19. \RequirePackage{amsmath}
38 |
39 | References:
40 | 20. \RequirePackage{bibentry}
41 |
42 | Misc:
43 | 21. \RequirePackage[hidelinks]{hyperref}
44 | 22. \RequirePackage{url}
45 | 23. \RequirePackage{lastpage}
46 | 24. \RequirePackage{titlesec}
47 |
--------------------------------------------------------------------------------
/dfg_proposal_en.cls:
--------------------------------------------------------------------------------
1 | \NeedsTeXFormat{LaTeX2e}[2017/04/15]
2 |
3 | \ProvidesClass{dfg_proposal_en}[Latex DFG Basic Module in English]
4 | \LoadClass[a4paper,11pt]{article}
5 |
6 | \RequirePackage[utf8]{inputenc}
7 | \RequirePackage[english]{babel}
8 | \RequirePackage{anyfontsize}
9 | \RequirePackage{microtype}
10 | \RequirePackage{geometry}
11 | \geometry{a4paper, left=1.7cm, right=1.8cm, top=2.0cm, bottom=1.5cm, headheight=1.0cm}
12 | \RequirePackage{fancyhdr}
13 | \RequirePackage{indentfirst}
14 | \RequirePackage[official]{eurosym}
15 | \RequirePackage[dvipsnames]{xcolor}
16 | \definecolor{dfgblue}{RGB}{0, 82, 158}
17 |
18 | \RequirePackage{graphicx}
19 | \RequirePackage[font=normal,labelfont=bf]{caption}
20 | \RequirePackage{subfig}
21 | \RequirePackage{wrapfig}
22 |
23 | \RequirePackage{threeparttable}
24 | \RequirePackage{booktabs}
25 | \RequirePackage[labelfont=bf]{caption}
26 | \RequirePackage{colortbl}
27 |
28 | \RequirePackage{amsmath}
29 |
30 | \RequirePackage[hidelinks]{hyperref}
31 | \RequirePackage{url}
32 | \RequirePackage{bibentry}
33 | \nobibliography*
34 |
35 | \renewcommand{\rmdefault}{phv} % Arial
36 | \renewcommand{\sfdefault}{phv} % Arial
37 |
38 | \RequirePackage{lastpage}
39 | \pagestyle{fancy}
40 | \renewcommand{\headrulewidth}{0.0pt}
41 | \renewcommand{\footrulewidth}{0.0pt}
42 | \lhead{\fontsize{8.5}{10} DFG form 53.01 -- 03/18}
43 | \cfoot{}
44 | \rhead{\fontsize{8.5}{10} page \thepage ~of \pageref{LastPage}}
45 |
46 | \fancypagestyle{firstpagefooter}{%
47 | \fancyhf{}
48 | \lhead{\fontsize{8.5}{10} DFG form 53.01 -- 03/18}
49 | \rhead{\fontsize{8.5}{10} page \thepage ~of \pageref{LastPage}}
50 | \setlength\footskip{40pt}
51 | \fancyfoot[L]{\begin{minipage}{0.85\textwidth}\fontsize{8.5}{10}Deutsche Forschungsgemeinschaft\\
52 | Kennedyallee 40 $\cdot$ 53175 Bonn $\cdot$ postal address: 53170 Bonn\\
53 | phone: + 49 228 885-1 $\cdot$ fax: + 49 228 885-2777 $\cdot$ postmaster@dfg.de $\cdot$ www.dfg.de\end{minipage}
54 | \fontsize{33.0}{44}{\textcolor{dfgblue}{\textbf{\bigskip DFG}}}}
55 | }
56 |
57 | \RequirePackage{titlesec}
58 | \setcounter{secnumdepth}{4}
59 | \titleformat*{\section}{\normalsize\bfseries}
60 | \titleformat*{\subsection}{\normalsize\bfseries}
61 | \titleformat*{\subsubsection}{\normalsize\bfseries}
62 | \titleformat*{\paragraph}{\normalsize\bfseries}
63 | \titleformat*{\subparagraph}{\normalsize\bfseries}
64 |
65 | \titleclass{\subsubsubsection}{straight}[\subsection]
66 | \newcounter{subsubsubsection}[subsubsection]
67 | \renewcommand\thesubsubsubsection{\thesubsubsection.\arabic{subsubsubsection}}
68 | \titleformat{\subsubsubsection}
69 | {\normalfont\normalsize\bfseries}{\thesubsubsubsection}{1em}{}
70 | \titlespacing*{\subsubsubsection}{0pt}{1.5ex plus 0.2ex minus .2ex}{1.5ex plus .2ex}
71 | \newcommand{\toclevel@subsubsubsection}{4}
72 |
--------------------------------------------------------------------------------
/dfg_proposal_en.tex:
--------------------------------------------------------------------------------
1 | \documentclass[red]{dfg_proposal_en}
2 | \usepackage[utf8]{inputenc}
3 | \usepackage[english]{babel}
4 |
5 | \usepackage{lipsum}
6 |
7 | \usepackage{nicefrac} % compact symbols for 1/2, etc.
8 |
9 | \usepackage[hidelinks]{hyperref} % hyperlinks
10 | \usepackage{url} % simple URL typesetting
11 |
12 | \newcommand{\kcalmol}{kcal$\cdot$mol$^{\text{-}1}$}
13 |
14 | \title{DFG Grant Proposal}
15 | \author{Karl N. Kirschner}
16 | \date{\today}
17 |
18 | \usepackage{afterpage}
19 | \begin{document}
20 | \newgeometry{left=1.7cm,right=1.8cm,top=2.0cm,bottom=3.0cm,headheight=1.0cm}
21 | \afterpage{\aftergroup\restoregeometry}
22 | \thispagestyle{firstpagefooter}
23 |
24 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25 | %% Based on 54_012_en-proposal-template.pdf
26 |
27 | \section*{\normalsize Project Description -- Project Proposals}
28 | \noindent Karl N. Kirschner, Sankt Augustin\\
29 | Fixed Term
30 |
31 | \hrulefill
32 | \bigskip
33 |
34 | % Basic Module
35 | % Use the basic module to request funding for direct project costs, project-specific staff, and instrumentation necessary to carry out the project, as well as an allowance for the publication of project findings.
36 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 | \noindent\textbf{Project Description}
38 | \section{State of the art and preliminary work} % 1 section
39 | [Text]
40 |
41 | \subsection{Project-related publications} % 1.1 section
42 |
43 | \subsubsection{Articles published by outlets with scientific quality assurance, book publications, and works accepted for publication but not yet published} % 1.1.1 section
44 | % Up to 10 papers. If first submission, then list the important ones.
45 | \begin{enumerate}
46 | \item \bibentry{}
47 | \item \bibentry{}
48 | \item \bibentry{}
49 | \item \bibentry{}
50 | \item \bibentry{}
51 | \item \bibentry{}
52 | \item \bibentry{}
53 | \item \bibentry{}
54 | \item \bibentry{}
55 | \item \bibentry{}
56 | \end{enumerate}
57 |
58 | \subsubsection{Other publications} % 1.1.2 section
59 | %% This might be posters, reviews and invited talks. Ask the DFG person responsible - writing nothing is usually bad.
60 | [Text]
61 |
62 | \subsubsection{Patents} % 1.1.3 section
63 | \subsubsubsection{Pending} % 1.1.3.1 section
64 | [Text]
65 |
66 | \subsubsubsection{\normalsize Issued} % 1.1.3.2 section
67 | [Text]
68 |
69 |
70 | \section{Objectives and work program} % 2 section
71 | \subsection{Anticipated total duration of the project} % 2.1 section
72 | [Text]
73 |
74 | \subsection{Objectives} % 2.2 section
75 | [Text]
76 |
77 | \subsection{Work program incl. proposed research methods} % 2.3 section
78 | \textit{For each applicant}
79 |
80 | [Text]
81 |
82 | \subsection{Data handling} %% 2.4 section
83 | [Text]
84 |
85 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
86 | \subsection{Other information} %% 2.5 section
87 | \textit{Please use this section for any additional information you feel is relevant which has not been provided elsewhere.}
88 |
89 | [Text]
90 |
91 | \subsection{Descriptions of proposed investigations involving experiments on humans, human materials or animals as well as dual use research of concern} %% 2.6 section
92 | [Text]
93 |
94 | \subsection{Information on scientific and financial involvement of international cooperation partners} %% 2.7 section
95 | [Text]
96 |
97 |
98 | \section{Bibliography} %% 3 section
99 | \renewcommand{\refname}{}
100 | \bibliographystyle{unsrt}
101 | \bibliography{references}
102 |
103 |
104 | %\setcounter{section}{3}
105 | \section{Requested modules/funds} %% 4 section
106 | \textit{Explain each item for each applicant (stating last name, first name).}
107 |
108 | \subsection{Basic Module} %% 4.1 section
109 |
110 | \subsubsection{Funding for Staff} %% 4.2 section\\
111 |
112 | [Text]
113 |
114 | \subsubsection{Direct Project Costs} %% 4.3 section
115 | [Text]
116 |
117 | \subsubsubsection{Equipment up to Euro 10,000, Software and Consumables}
118 | [Text]
119 |
120 | \subsubsubsection{Travel Expenses}
121 | [Text]
122 |
123 | \subsubsubsection{Visiting Researchers (excluding Mercator Fellows)}
124 | [Text]
125 |
126 | \subsubsubsection{Expenses for Laboratory Animals}
127 | [Text]
128 |
129 | \subsubsubsection{Other Costs}
130 | [Text]
131 |
132 | \subsubsubsection{Project-related publication expenses}
133 | [Text]
134 |
135 | \subsubsection{Instrumentation}
136 | [Text]
137 |
138 | \subsubsubsection{Equipment exceeding Euro 10,000}
139 | [Text]
140 |
141 | \subsubsubsection{Major Instrumentation exceeding Euro 50,000}
142 | [Text]
143 |
144 | \subsection{Module Temporary Position for Principal Investigator}
145 | [Text]
146 |
147 | \subsection{Module Replacement Funding}
148 | [Text]
149 |
150 | \subsection{Module Temporary Clinician Substitute}
151 | [Text]
152 |
153 | \subsection{Module Mercator Fellows}
154 | [Text]
155 |
156 | \subsection{Module Public Relations Funding}
157 | [Text]
158 |
159 | \section{Project requirements}
160 |
161 | \subsection{Employment status information}
162 | \textit{For each applicant, state the last name, first name, and employment status (including duration of contract and funding body, if on a fixed-term contract).}
163 |
164 | [Text]
165 |
166 | \subsection{First-time proposal data}
167 | \textit{Only if applicable: Last name, first name of first-time applicant}
168 |
169 | [Text]
170 |
171 | \subsection{Composition of the project group}
172 | [Text]
173 |
174 | \subsection{Composition of the project group}
175 | \textit{List only those individuals who will work on the project but will not be paid out of the project funds. State each person’s name, academic title, employment status, and type of funding.}
176 |
177 | [Text]
178 |
179 | \subsection{Cooperation with other researchers}
180 |
181 | \subsubsection{Researchers with whom you have agreed to cooperate on this project}
182 | [Text]
183 |
184 | \subsubsection{Researchers with whom you have collaborated scientifically within the past three years}
185 | [Text]
186 |
187 | \subsection{Scientific equipment}
188 | \textit{List larger instruments that will be available to you for the project. These may include large computer facilities if computing capacity will be needed. }
189 |
190 | [Text]
191 |
192 | \subsection{Project-relevant cooperation with commercial enterprises}
193 | \textit{If applicable, please note the EU guidelines on state aid or contact your research institution in this regard.}
194 |
195 | [Text]
196 |
197 | \subsection{Project-relevant participation in commercial enterprises}
198 | \textit{Information on connections between the project and the production branch of the enterprise}
199 |
200 | [Text]
201 |
202 | \section{Composition of the project group}
203 | [Text]
204 |
205 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
206 | \section{Additional information} %% 6 section
207 | \textit{If applicable, please list proposals requesting major instrumentation and/or those previously submitted to a third party here.}
208 |
209 | [Text]
210 |
211 | \end{document}
--------------------------------------------------------------------------------
/scientific_programming.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "id": "KFQGXReai-lA"
7 | },
8 | "source": [
9 | "
\n",
10 | "\n",
11 | "#
Scientific Programming in Python\n",
12 | "## Karl N. Kirschner
Bonn-Rhein-Sieg University of Applied Sciences
Sankt Augustin, Germany\n",
13 | "\n",
14 | "# Scientific Programming Practices\n",
15 | "\n",
16 | "
\n",
17 | "\n",
18 | "\n",
19 | "Primary source: [Wilson, G., Aruliah, D.A., Brown, C.T., Hong, N.P.C., Davis, M., Guy, R.T., Haddock, S.H., Huff, K.D., Mitchell, I.M., Plumbley, M.D. and Waugh, B., 2014. Best practices for scientific computing. PLoS biology, 12, 1-7.](https://journals.plos.org/plosbiology/article?id=10.1371/journal.pbio.1001745)"
20 | ]
21 | },
22 | {
23 | "cell_type": "markdown",
24 | "metadata": {
25 | "id": "O7_uoSoKi-lD"
26 | },
27 | "source": [
28 | "
\n",
29 | "\n",
30 | "\"Computers are now essential in all branches of science, but most researchers are never taught the equivalent of basic lab skills for research computing. As a result, they ... are often unable to reproduce their own work ... and have no idea how reliable their computational results are.\"\n",
31 | "\n",
32 | "Wilson, Greg, Jennifer Bryan, Karen Cranston, Justin Kitzes, Lex Nederbragt, and Tracy K. Teal. \"Good enough practices in scientific computing.\" PLoS computational biology 13, no. 6 (2017).\n",
33 | "\n",
34 | "
"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "ClXeAMSTi-lD"
41 | },
42 | "source": [
43 | "# The 7 practices for programming within research settings"
44 | ]
45 | },
46 | {
47 | "cell_type": "markdown",
48 | "metadata": {
49 | "id": "oMQyRj2yi-lE"
50 | },
51 | "source": [
52 | "\n",
53 | "## 1. Write programs for people, not computers\n",
54 | "\n",
55 | "Why\n",
56 | "\n",
57 | "1. The reader will only hold a few facts in memory at a time.\n",
58 | "\n",
59 | "How\n",
60 | "\n",
61 | "1. Break the program up into easy understandable chunks (i.e., functions).\n",
62 | "2. Use names that are consistent, distinctive and meaningful (e.g., \"density\" vs. \"d\").\n",
63 | "3. Use a consistent coding style\n",
64 | " - PascalCaseNaming\n",
65 | " - camelCaseNaming\n",
66 | " - snake/pothole_case_naming\n",
67 | " - kebab-case-naming\n",
68 | "4. PEP8: \"Function names should be lowercase, with words separated by underscores as necessary to improve readability.\"
\n",
69 | " (ie., pothole_case_naming)\n",
70 | "\n",
71 | "Example\n",
72 | "\n",
73 | "Poorly done:"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": null,
79 | "metadata": {
80 | "id": "ZCgYejS1i-lF"
81 | },
82 | "outputs": [],
83 | "source": [
84 | "print('Input velocity:')\n",
85 | "l = 299.7e6\n",
86 | "v = input()\n",
87 | "print(f'{v} m/s is {(float(v)/l)*100:0.1e}%')"
88 | ]
89 | },
90 | {
91 | "cell_type": "markdown",
92 | "metadata": {
93 | "id": "LdgI1mx3i-lG"
94 | },
95 | "source": [
96 | "Improved upon:"
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": null,
102 | "metadata": {
103 | "id": "6L6Fsomgi-lG"
104 | },
105 | "outputs": [],
106 | "source": [
107 | "speed_of_light = 2.99792458e8 # m/s\n",
108 | "\n",
109 | "print('What velocity are you interested in (units: m/s)?')\n",
110 | "input_velocity = input()\n",
111 | "\n",
112 | "percentage = (float(input_velocity)/speed_of_light)*100\n",
113 | "\n",
114 | "print(f'The input velocity of {input_velocity} m/s is {percentage:0.1e}% of the speed of light.')"
115 | ]
116 | },
117 | {
118 | "cell_type": "markdown",
119 | "metadata": {
120 | "id": "fcYmY4zIi-lG"
121 | },
122 | "source": [
123 | "
\n",
124 | "\n",
125 | "\n",
126 | "## 2. Have the computer do the work\n",
127 | "\n",
128 | "Why\n",
129 | " 1. User repetition eventually results in errors, even with those who are careful\n",
130 | "\n",
131 | "How\n",
132 | " 1. Create code that does the repeating element\n",
133 | " \n",
134 | " 2. Create code that allows sequential workflow usage and modulation\n",
135 | " \n",
136 | " 3. Save commands to file for future use\n",
137 | " \n",
138 | " 4. Ensure reproducibility\n",
139 | " - Everything needed to re-create the output should be clear\n",
140 | " - Standardize the output\n",
141 | " - Version control, even as simple as using a numbering system (e.g., v.0.1)\n",
142 | "\n",
143 | "Example: Given the length of two triangles, get their total area. Print out all areas."
144 | ]
145 | },
146 | {
147 | "cell_type": "code",
148 | "execution_count": null,
149 | "metadata": {
150 | "id": "Vm8h4xlai-lH"
151 | },
152 | "outputs": [],
153 | "source": [
154 | "## Poor Example\n",
155 | "area_total = 4.0*3.0 + 0.5*1.5\n",
156 | "\n",
157 | "print(f'Rectangle Area 1: {4.0*3.0}')\n",
158 | "print(f'Rectangle Area 2: {0.5*2.5}')\n",
159 | "print(f'Total Area: {area_total}')"
160 | ]
161 | },
162 | {
163 | "cell_type": "markdown",
164 | "metadata": {
165 | "id": "A9rgYQzzi-lI"
166 | },
167 | "source": [
168 | "Why is it poorly done?\n",
169 | "1. There is no single statement that will calculate the area of 1 rectangle\n",
170 | "2. Not very modular, nor is it very readable\n",
171 | "3. Prone to human error - e.g. print('Rectangle Area 2:', 0.5*2.5)\n",
172 | "4. Not logically planned out"
173 | ]
174 | },
175 | {
176 | "cell_type": "code",
177 | "execution_count": null,
178 | "metadata": {
179 | "id": "rGZ6Z4Ebi-lJ"
180 | },
181 | "outputs": [],
182 | "source": [
183 | "## Better Example\n",
184 | "def rectangle_area(length: float, width: float) -> float:\n",
185 | " rect_area = length*width\n",
186 | "\n",
187 | " return rect_area\n",
188 | "\n",
189 | "\n",
190 | "area_1 = None\n",
191 | "area_2 = None\n",
192 | "area_total = None\n",
193 | "\n",
194 | "area_1 = rectangle_area(length=4.0, width=3.0)\n",
195 | "area_2 = rectangle_area(length=0.5, width=1.5)\n",
196 | "\n",
197 | "area_total = area_1 + area_2\n",
198 | "\n",
199 | "print(f'Rectangle Area 1: {area_1}\\n'\n",
200 | " f'Rectangle Area 2: {area_2}\\n'\n",
201 | " f'Total Area: {area_total}')"
202 | ]
203 | },
204 | {
205 | "cell_type": "markdown",
206 | "metadata": {
207 | "id": "5zH4nC-Ji-lK"
208 | },
209 | "source": [
210 | "Why is this better?\n",
211 | "1. A function that does one thing (i.e., isolates a single idea) that can be called multiple times\n",
212 | "2. Less prone to introducing errors due to the function\n",
213 | "3. Easy to debug and modify\n",
214 | "4. Better logical construction"
215 | ]
216 | },
217 | {
218 | "cell_type": "markdown",
219 | "metadata": {
220 | "id": "ZhGQt2W-i-lK"
221 | },
222 | "source": [
223 | "
\n",
224 | "\n",
225 | "\n",
226 | "## 3. Don't repeat yourself, or others\n",
227 | "\n",
228 | "Why\n",
229 | "1. Repeating code makes things harder to maintain and increases the chances of introducing errors\n",
230 | "\n",
231 | "How\n",
232 | "1. DRY - \"Don't Repeat Yourself,\" applying this to both code and data\n",
233 | " - One code representation per entity.\n",
234 | " \n",
235 | " Example 1: physical constants should be defined once\n",
236 | " \n",
237 | " Example 2: input raw data should be assigned to a single variable (i.e., not duplicated)\n",
238 | " \n",
239 | "2. Modularize your code (e.g., user-defined functions)\n",
240 | "\n",
241 | "\n",
242 | "3. Use reliable libraries made by others (Python is very good at this) - don't reinvent the wheel"
243 | ]
244 | },
245 | {
246 | "cell_type": "markdown",
247 | "metadata": {
248 | "id": "WoDvo7NKi-lK"
249 | },
250 | "source": [
251 | "
\n",
252 | "\n",
253 | "\n",
254 | "## 4. Make small incremental (sequential) changes\n",
255 | "\n",
256 | "Why\n",
257 | "1. Typically, in scientific programming intended for research, the result is not initially known since each step depends on the previous one.\n",
258 | "\n",
259 | "1. In research-related work, there is not the idea of preset requirements (e.g., from a company). Therefore, this gives one more flexibility and creativity in the programming and approach.\n",
260 | "\n",
261 | "How\n",
262 | "1. Work in small steps (e.g., something doable in 1 hour - increased focus)\n",
263 | "\n",
264 | "1. Work on steps that are sequential (i.e., a logically connected workflow)\n",
265 | "\n",
266 | "1. Have frequent discussions and course corrections (with those who will use the program)\n",
267 | "\n",
268 | "1. Use a version control system (i.e., git) - also ensures reproducibility (i.e., important for science)\n",
269 | "\n",
270 | "1. Use unit tests and internal checks - help to control errors and directs your logical thinking\n",
271 | " \n",
272 | "1. Make small changes (especially with units tests) helps to quickly isolate errors\n",
273 | "\n",
274 | "Take-Home Message\n",
275 | "1. Ensures a more logical construction of the code and ideas (i.e., sequential and focused workflows)\n",
276 | " \n",
277 | "1. Reduces errors (i.e., highly focused upon a single concept at a time)\n",
278 | " \n",
279 | "1. Generates more flexible code (e.g., due to different users communicating different desires)"
280 | ]
281 | },
282 | {
283 | "cell_type": "markdown",
284 | "metadata": {
285 | "id": "LKCbYYIAi-lK"
286 | },
287 | "source": [
288 | ""
297 | ]
298 | },
299 | {
300 | "cell_type": "markdown",
301 | "metadata": {
302 | "id": "3wrnthUZi-lL"
303 | },
304 | "source": [
305 | "
\n",
306 | "\n",
307 | "\n",
308 | "## 5. Document the design and pupose (not the mechanics)\n",
309 | "\n",
310 | "Why\n",
311 | "1. Helps people understand the code - context\n",
312 | " - e.g., \"This function computes ...\"\n",
313 | "\n",
314 | "2. Helps to maintain continuity (e.g., long-term projects)\n",
315 | "\n",
316 | "How\n",
317 | "\n",
318 | "1. Embed documentation in the code (helps with longevity and changes in people)\n",
319 | " 1. docstrings (a.k.a., block quotes) (i.e. text within triple quotes: `'''` or `\"\"\"`)\n",
320 | " - Usage:\n",
321 | " - Python3 programs (e.g., stat_thermo.py): proving context throughout the code\n",
322 | " - Jupyter-notebooks' code cells: when providing context for a user-defined function\n",
323 | "\n",
324 | " - Results in\n",
325 | " - allowing others to get instructions for usage via (see code cells below)\n",
326 | " - `my_function.__doc__`, or\n",
327 | " - `help(my_function)`\n",
328 | "\n",
329 | " - Focus upon\n",
330 | " - what is the code's purpose/goals are,\n",
331 | " - what input is required (e.g., passed objects/variables), and\n",
332 | " - what output is given\n",
333 | "\n",
334 | " - However, don't be redundant\n",
335 | " - the code itself should be readable and speakable, and thus lessening the need for extensive documentation\n",
336 | "\n",
337 | " - Documentation generator that can read the code and make a manual (e.g., sphinx-doc: https://www.sphinx-doc.org/en/master/)\n",
338 | "\n",
339 | " 2. In-line comments\n",
340 | " - Usage:\n",
341 | " - Python3 programs and Jupyter-notebook code cells\n",
342 | "\n",
343 | " - If done well (concise, logical, readable), you should not need many in-line comments to explain your code.\n",
344 | "\n",
345 | " Example for not needed:
\n",
346 | " `if input <= threshold: #if input is less than or equal to a threshold then do` is readable, and thus this line does not need to be further explained by the in-line comment.\n",
347 | "\n",
348 | " Example for when one is needed:
\n",
349 | " `energy_total = 0.3*alpha + 0.7*beta # The weighting factors come from reference 3.`
\n",
350 | " This in-line comment clearly states the published source of the used weighting factors. \n",
351 | "\n",
352 | " - Use if you think your very local coding idea (i.e. given on a single line) might be unclear, or if an unaddressed assumption/approximation needs to be explained.\n",
353 | "\n",
354 | "2. Document your thought process, gained insights and to cite sources of information (i.e. existing knowledge)\n",
355 | "\n",
356 | " 1. markdown cells\n",
357 | " - Usage:\n",
358 | " - Jupyter-notebooks: when providing context for a specific project, or to pass on information to other who might use or look at your notebook.\n",
359 | "\n",
360 | " - Consider markdown usage to be like the communication that occurs in traditional academic lab notebooks.\n",
361 | " \n",
362 | " Example Statement within a Markdown Cell:
\n",
363 | " \"The above plot show several significant outliners. Thus, we extracted the outliers and correlated their values to their input features using sklearn's function (website). This lead to the identification of the following new categories: ... \"\n",
364 | "\n",
365 | "Example:"
366 | ]
367 | },
368 | {
369 | "cell_type": "code",
370 | "execution_count": null,
371 | "metadata": {
372 | "id": "67aml5fri-lL"
373 | },
374 | "outputs": [],
375 | "source": [
376 | "def rectangle_area(length, width):\n",
377 | " \"\"\" Computes a rectangle's area using its length and height.\n",
378 | "\n",
379 | " Args: length - the length of the first edge\n",
380 | " height - the length of the second edge\n",
381 | " (must be at a right angle to the first edge)\n",
382 | " Return: rect_area - the calculated area of a rectangle\n",
383 | " \"\"\"\n",
384 | "\n",
385 | " rect_area = None\n",
386 | " rect_area = length*width\n",
387 | "\n",
388 | " return rect_area"
389 | ]
390 | },
391 | {
392 | "cell_type": "code",
393 | "execution_count": null,
394 | "metadata": {
395 | "id": "1-5fWE8Fi-lL"
396 | },
397 | "outputs": [],
398 | "source": [
399 | "print(rectangle_area.__doc__)"
400 | ]
401 | },
402 | {
403 | "cell_type": "code",
404 | "execution_count": null,
405 | "metadata": {
406 | "id": "M-GHIyDmi-lL"
407 | },
408 | "outputs": [],
409 | "source": [
410 | "help(rectangle_area)"
411 | ]
412 | },
413 | {
414 | "cell_type": "markdown",
415 | "metadata": {
416 | "id": "Ali22kIWi-lM"
417 | },
418 | "source": [
419 | "
\n",
420 | "\n",
421 | "\n",
422 | "## 6. Collaborate\n",
423 | "\n",
424 | "Why\n",
425 | "1. This is similar to \"Peer Review\", where other people\n",
426 | " - read your code,\n",
427 | " - use your code in unexpected ways,\n",
428 | " - bring their perspective to your ideas, and\n",
429 | " - provide quality control and feedback.\n",
430 | "\n",
431 | "How\n",
432 | "1. Have a central location for the code (e.g., Github, Dropbox)\n",
433 | " \n",
434 | "2. Sit down and co-code together (or through online servers, e.g., discord)\n",
435 | " \n",
436 | "3. Give it to others and have them run the code\n",
437 | "\n",
438 | "4. Give credit/acknowledgment to everyone who contributed to the ideas and writing"
439 | ]
440 | },
441 | {
442 | "cell_type": "markdown",
443 | "metadata": {
444 | "id": "h7Un-Zj-i-lM"
445 | },
446 | "source": [
447 | "
\n",
448 | "\n",
449 | "\n",
450 | "## 7. Plan for Mistakes\n",
451 | "\n",
452 | "Why Because mistakes will happen by you and by the program's user.\n",
453 | "\n",
454 | "How\n",
455 | "\n",
456 | "1. Use `isinstance` statements
\n",
457 | "\n",
458 | "2. Use `assert` statements (if True ...) to check the program's operation while developing code\n",
459 | " - They stop the program if something is wrong\n",
460 | " - Think of them as executable documentation (i.e. explains what is going on within the code)\n",
461 | " - (However, asserts do have some issues with their usage --- next lecture)
\n",
462 | " \n",
463 | "3. Take a divide-and-conquer approach to coding: simplify the code and problems\n",
464 | " - e.g., user-defined functions
\n",
465 | "\n",
466 | "4. Turn bugs into test cases (e.g., in a unit test framework)
\n",
467 | " \n",
468 | "5. (Unit tests - automated test on a single \"unit\" of code)
\n",
469 | " - unittest (built-in library)- https://docs.python.org/3/library/unittest.html\n",
470 | " - pytest - https://docs.pytest.org\n",
471 | "\n",
472 | "6. (Integration tests - test if units of code work together)
\n",
473 | " \n",
474 | "7. (Regression tests - the program's behavior doesn't change when the program's details are modified)\n",
475 | " - e.g., the output data is presented and remains the same
\n",
476 | " \n",
477 | "8. (Try-except statements - handle exceptions; https://docs.python.org/3/tutorial/errors.html)
\n",
478 | " \n",
479 | "Note 1: Tests are often done to see if the code's output matches the researcher's expectations. That means you must have a good understanding of the problem.\n",
480 | " \n",
481 | "Note 2: Test can often initially be done on simpler systems
\n",
482 | "\n",
483 | "Example: Add an `isinstance` statement. Alternatively, add an `assert` statements to the circle_area function (see point #2 above), and then supply the function with a negative radius."
484 | ]
485 | },
486 | {
487 | "cell_type": "code",
488 | "execution_count": null,
489 | "metadata": {
490 | "id": "Rmrpm6nEi-lM"
491 | },
492 | "outputs": [],
493 | "source": [
494 | "from math import pi\n",
495 | "\n",
496 | "\n",
497 | "def circle_area(radius_input: float) -> float:\n",
498 | " ''' Compute the area of a circle\n",
499 | "\n",
500 | " Input:\n",
501 | " radius: radius of a circle\n",
502 | " Return:\n",
503 | " area: area of a circle\n",
504 | " '''\n",
505 | " if not isinstance(radius_input, float):\n",
506 | " raise TypeError(f'The radius_input value (i.e. {radius_input}) was not a float.')\n",
507 | "\n",
508 | " #assert (radius_input >= 0), f'The radius value (i.e. {radius_input}) must be positive.'\n",
509 | "\n",
510 | " circle_area = None\n",
511 | " circle_area = pi*(radius_input2)\n",
512 | "\n",
513 | " return circle_area\n",
514 | "\n",
515 | "\n",
516 | "radii = [1.0, 2.0, -2.5, 3.0]\n",
517 | "\n",
518 | "for radius in radii:\n",
519 | " area = circle_area(radius_input=radius)\n",
520 | " print(f'Area of circle with radius of {radius:0.1f}: {area:0.1e}')"
521 | ]
522 | },
523 | {
524 | "cell_type": "code",
525 | "execution_count": null,
526 | "metadata": {
527 | "id": "21pNMvjsi-lN"
528 | },
529 | "outputs": [],
530 | "source": [
531 | "circle_area(radius_input=5)"
532 | ]
533 | },
534 | {
535 | "cell_type": "markdown",
536 | "metadata": {
537 | "id": "MggYDchMi-lN"
538 | },
539 | "source": [
540 | "Unittest require a bit more knowledge to understand their structure (e.g., class, self), but below is a very simple starting point for those who want to explore incorporating them into their Jupyter notebooks."
541 | ]
542 | },
543 | {
544 | "cell_type": "code",
545 | "execution_count": null,
546 | "metadata": {
547 | "id": "lOrUnu03i-lN"
548 | },
549 | "outputs": [],
550 | "source": [
551 | "import unittest"
552 | ]
553 | },
554 | {
555 | "cell_type": "code",
556 | "execution_count": null,
557 | "metadata": {
558 | "id": "zT3ceRJYi-lO"
559 | },
560 | "outputs": [],
561 | "source": [
562 | "class Testing(unittest.TestCase):\n",
563 | " def test_string(self):\n",
564 | " a = 'some'\n",
565 | " b = 'some'\n",
566 | " self.assertEqual(a, b)\n",
567 | "\n",
568 | " def test_boolean(self):\n",
569 | " a = True\n",
570 | " b = True\n",
571 | " self.assertEqual(a, b)\n",
572 | "\n",
573 | "\n",
574 | "# execute Testing class (and its functions) when the cell is executed\n",
575 | "unittest.main(argv=[''], verbosity=2, exit=False)"
576 | ]
577 | },
578 | {
579 | "cell_type": "markdown",
580 | "metadata": {
581 | "id": "EhdnBfqhi-lO"
582 | },
583 | "source": [
584 | "Applying to use our `circle_area` function above:"
585 | ]
586 | },
587 | {
588 | "cell_type": "code",
589 | "execution_count": null,
590 | "metadata": {
591 | "id": "U-7X64Rci-lO"
592 | },
593 | "outputs": [],
594 | "source": [
595 | "class Testing(unittest.TestCase):\n",
596 | " def test_area_correct(self):\n",
597 | " area = circle_area(radius_input=1.0)\n",
598 | " target_area = 3.141592653589793\n",
599 | "\n",
600 | " self.assertEqual(area, target_area)\n",
601 | "\n",
602 | " def test_area_incorrect(self):\n",
603 | " area = circle_area(radius_input=1.0)\n",
604 | " target_area = 3.1\n",
605 | "\n",
606 | " self.assertEqual(area, target_area)\n",
607 | "\n",
608 | "\n",
609 | "unittest.main(argv=[''], verbosity=2, exit=False)"
610 | ]
611 | }
612 | ],
613 | "metadata": {
614 | "kernelspec": {
615 | "display_name": "Python 3 (ipykernel)",
616 | "language": "python",
617 | "name": "python3"
618 | },
619 | "language_info": {
620 | "codemirror_mode": {
621 | "name": "ipython",
622 | "version": 3
623 | },
624 | "file_extension": ".py",
625 | "mimetype": "text/x-python",
626 | "name": "python",
627 | "nbconvert_exporter": "python",
628 | "pygments_lexer": "ipython3",
629 | "version": "3.11.9"
630 | },
631 | "colab": {
632 | "provenance": []
633 | }
634 | },
635 | "nbformat": 4,
636 | "nbformat_minor": 0
637 | }
--------------------------------------------------------------------------------