Skip to content

Commit 609ec51

Browse files
add scripting exercise and extend getting started
1 parent 760bd8c commit 609ec51

9 files changed

+142
-70
lines changed

book/01_1_getting_started.ipynb

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,20 @@
1616
"id": "32684093-9150-48ce-8c92-74fa4277905d",
1717
"metadata": {},
1818
"source": [
19-
"## Introduction\n",
20-
"For historical and technical reasons installing Python and managing dependencies is more cumbersome than it should be and as of today (October 2024) there are way too many ways to deal with those problems.\n",
21-
"My recommendation here is: Pick one system that works for you and stick to it.\n",
22-
"\n",
19+
"## Set up your code editor\n",
20+
"When editing code more extensively we want to have a so called integrated development environment (IDE).\n",
21+
"There are many options out there.\n",
22+
"Do not spend too much time deciding which to pick, you can always change your choice later. \n",
23+
"[VS-Code](https://code.visualstudio.com/) is a reasonable general choice as of today, it is free and widely adopted.\n",
24+
"For a user experience more similar to matlab or R-studio and oriented to scientific computing you can check out [Spyder](https://www.spyder-ide.org)."
25+
]
26+
},
27+
{
28+
"cell_type": "markdown",
29+
"id": "1100eea3-69e1-4833-abe5-bd852d84720e",
30+
"metadata": {},
31+
"source": [
32+
"## Set up Python with `uv`\n",
2333
"We essentially need to carry out three tasks:\n",
2434
"\n",
2535
"- Install Python (the language itself)\n",
@@ -34,7 +44,7 @@
3444
"id": "fe4bbe76-976f-4782-9153-95937a54b880",
3545
"metadata": {},
3646
"source": [
37-
"## Install `uv`\n",
47+
"### Install `uv`\n",
3848
"\n",
3949
"Run only one of these commands in your terminal - pick according to your operating system:\n",
4050
"\n",
@@ -44,7 +54,11 @@
4454
"```\n",
4555
"\n",
4656
"**Windows** \n",
47-
"Make sure you are using **powershell**!\n",
57+
"\n",
58+
"::: {.callout-important}\n",
59+
"Make sure to use **powershell**! (default if you execute this in the VSCode terminal).\n",
60+
":::\n",
61+
"\n",
4862
"\n",
4963
"```bash\n",
5064
"powershell -ExecutionPolicy ByPass -c \"irm https://astral.sh/uv/install.ps1 | iex\"\n",
@@ -69,7 +83,7 @@
6983
"id": "96e086b1-d39b-4508-89ea-c258bdea61ed",
7084
"metadata": {},
7185
"source": [
72-
"## Working on a project\n",
86+
"### Working on a project\n",
7387
"To start a new project run in your terminal:\n",
7488
"\n",
7589
"```bash\n",
@@ -100,6 +114,18 @@
100114
"```"
101115
]
102116
},
117+
{
118+
"cell_type": "markdown",
119+
"id": "76d149f3-09ef-4621-a92b-3b8c96362294",
120+
"metadata": {},
121+
"source": [
122+
"## Set up Git and GitHub\n",
123+
"\n",
124+
"If you don't yet have one, [set up a free GitHub account](https://github.com/signup).\n",
125+
"\n",
126+
"Also, make sure to [install Git in your machine](https://github.com/git-guides/install-git)."
127+
]
128+
},
103129
{
104130
"cell_type": "markdown",
105131
"id": "e6ec7541-6fc9-41c4-9947-d965c96d6f5a",

book/01_2_executing_code.ipynb

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -162,19 +162,6 @@
162162
"7) Same but print it's execution time"
163163
]
164164
},
165-
{
166-
"cell_type": "markdown",
167-
"id": "5cea3d9c-127b-4074-87c5-8d13a88da514",
168-
"metadata": {},
169-
"source": [
170-
"## Code Editor\n",
171-
"When editing code more extensively we also want to have a so called integrated development environment (IDE).\n",
172-
"There are many options out there.\n",
173-
"Do not spend too much time deciding which to pick, you can always change your choice later. \n",
174-
"[VS-Code](https://code.visualstudio.com/) is a reasonable general choice as of today, it is free and widely adopted.\n",
175-
"For a user experience more similar to matlab or R-studio and oriented to scientific computing you can check out [Spyder](https://www.spyder-ide.org)."
176-
]
177-
},
178165
{
179166
"cell_type": "markdown",
180167
"id": "bd5b592f-4fca-4192-bb4f-d1f25063312d",

book/02_types_data_structures.ipynb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,11 +317,21 @@
317317
"metadata": {},
318318
"source": [
319319
"::: {.callout-tip}\n",
320-
"In case you want to learn more about floating point numbers you can watch this [great video](https://www.youtube.com/watch?v=PZRI1IfStY0), but for now: it is just a way that computers have to _approximately_ represent numbers.\n",
320+
"For now: A floating point is just a way that computers have to _approximately_ represent numbers.\n",
321321
"For the most part, we will not have to think too much about them starting our Python journey.\n",
322+
"\n",
323+
"In case you want to learn more about floating point numbers you can watch this great video:\n",
324+
"{{< video https://www.youtube.com/watch?v=PZRI1IfStY0 >}}\n",
325+
"\n",
322326
":::"
323327
]
324328
},
329+
{
330+
"cell_type": "markdown",
331+
"id": "c358262b-dcc7-4c0a-b80f-84d3ce89abb1",
332+
"metadata": {},
333+
"source": []
334+
},
325335
{
326336
"cell_type": "markdown",
327337
"id": "59888694-ad70-4a7d-82f3-9d83bc537a5f",

book/05_comprehensions.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@
395395
"name": "python",
396396
"nbconvert_exporter": "python",
397397
"pygments_lexer": "ipython3",
398-
"version": "3.10.13"
398+
"version": "3.13.3"
399399
}
400400
},
401401
"nbformat": 4,

book/061_dependencies.ipynb

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@
1616
"id": "c79acc5e-0543-4994-b09a-1af21a509cd2",
1717
"metadata": {},
1818
"source": [
19-
"In contrast to some built-in modules such as `pathlib` and `json` that we can import directly after installing python, there are third-party libraries that we want to use but need to be first installed, such as `numpy` and `pandas`.\n",
19+
"In contrast to the code that we ourselves write and can import or to some built-in modules such as `pathlib` and `json` that we can import directly after installing python, there are third-party libraries that we want to use but need to be first installed, such as `numpy` and `pandas`. \n",
2020
"This libraries are also called \"packages\".\n",
21+
"There are several repositories where people publish python packages and from which we can download them, but the official one is [PyPI](https://pypi.org) (Python Package Index).\n",
22+
"\n",
2123
"\n",
2224
"These are open-source libraries maintained mostly by voluntary contributions of people of the community – and you can also contribute to them!\n",
2325
"\n",
2426
"They are being actively developed and thus in permanent evolution.\n",
2527
"In order to avoid compatibility problems and to ensure reproducibility, we might want to specify the exact versions of the packages we use.\n",
26-
"It turns out that is not an easy problem and the reason why need a **package manager**."
28+
"It turns out that is not an easy problem and the reason why need a **package manager**.\n",
29+
"\n",
30+
"The good news is that `uv` does that for us too."
2731
]
2832
},
2933
{
@@ -39,7 +43,7 @@
3943
"id": "2dce4970-2fa6-43ea-958b-1ae6a379dc94",
4044
"metadata": {},
4145
"source": [
42-
"The current convention to specify dependencies (and other things) in python projects is to use a file called [`pyproject.toml`](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/) that looks like this:\n",
46+
"The standard to specify dependencies (and other things) in python projects is to use a file called [`pyproject.toml`](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/) that looks like this:\n",
4347
"\n",
4448
"```yaml\n",
4549
"[project]\n",
@@ -58,9 +62,14 @@
5862
"]\n",
5963
"```\n",
6064
"\n",
65+
"::: {.callout-note}\n",
66+
"Take a look at the `pyproject.toml` file in you project, we already have one that `uv` automatically created for us!\n",
67+
":::\n",
68+
"\n",
6169
"The \"dependencies\" section is the one we care about here.\n",
6270
"There we list all the third-party libraries that our project requires.\n",
6371
"Notice that we can specify both exact versions (with \"==\") as well as constraints (with \"<,>,>=,<=\").\n",
72+
"\n",
6473
"In general we don't want to deal manually with those aspects – that's the job of a package manager."
6574
]
6675
},
@@ -136,7 +145,7 @@
136145
"name": "python",
137146
"nbconvert_exporter": "python",
138147
"pygments_lexer": "ipython3",
139-
"version": "3.10.13"
148+
"version": "3.13.3"
140149
}
141150
},
142151
"nbformat": 4,

book/06_imports.ipynb

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"id": "eb6b0843-d4d9-4f63-b155-11739ba90398",
1717
"metadata": {},
1818
"source": [
19-
"Every Python installation has a number of modules that come by default.\n",
19+
"Every Python installation includes a number of modules by default.\n",
2020
"They are called collectively the \"Python Standard Library\" or \"built-in\" modules.\n",
2121
"\n",
2222
"Even though these modules are available in our computer, we cannot directly use them, we need to import them into our current namespace to actually use them.\n",
@@ -51,7 +51,7 @@
5151
"id": "0ca12de9-9840-417c-b41f-fd3032093c12",
5252
"metadata": {},
5353
"source": [
54-
"That means that the word pathlib is unknown in this context.\n",
54+
"That means that the word pathlib is unknown in this context (namespace). \n",
5555
"Let's bring it in:"
5656
]
5757
},
@@ -99,11 +99,17 @@
9999
"id": "a12b0f16-b0d7-45fe-b3fe-1d443199a117",
100100
"metadata": {},
101101
"source": [
102-
"We can also import only specific parts of the module:\n",
103-
"\n",
104-
"```python\n",
105-
"from pathlib import Path\n",
106-
"```"
102+
"We can also import only specific parts of the module (submodules):"
103+
]
104+
},
105+
{
106+
"cell_type": "code",
107+
"execution_count": null,
108+
"id": "15e3f4c3-4509-46b8-8a86-380a2f4131df",
109+
"metadata": {},
110+
"outputs": [],
111+
"source": [
112+
"from pathlib import Path"
107113
]
108114
},
109115
{
@@ -150,40 +156,73 @@
150156
"id": "3b452c0b-682f-4868-9fd6-4dc6f7a5ff69",
151157
"metadata": {},
152158
"source": [
153-
"## Script vs. exportable code\n",
154-
"A Python module (any `.py` file) might contain code that we want to run (for example as a one-off script) along code that we only want to use somewhere else. \n",
155-
"For example, we might have a bunch of code like this in a file:\n",
159+
"## Script vs. Importable Code\n",
160+
"We can also import code that we wrote ourselves with the same syntax.\n",
161+
"For example, if we have a python file called `mymodule.py` we can import it from another file with:\n",
162+
"\n",
163+
"```python\n",
164+
"import mymodule\n",
165+
"```\n",
156166
"\n",
167+
"A Python module (any `.py` file) might contain code that we want to run (for example as a one-off script) along code that we only want to use somewhere else. \n",
157168
"We can isolate the part of the code that we want to run as a script with this trick.\n",
158169
"\n",
170+
"That's easier to show than to explain, so let's do some exercises."
171+
]
172+
},
173+
{
174+
"cell_type": "markdown",
175+
"id": "ee8413b5-b03f-456f-8298-a82feda2b076",
176+
"metadata": {},
177+
"source": [
178+
"## Exercises\n",
179+
"Create 2 files like these in our working project \n",
180+
"`/pycourse/src/pycourse/data.py`, `/pycourse/src/pycourse/preprocessing.py`:\n",
181+
"\n",
182+
"\n",
159183
"```python\n",
160184
"# data.py\n",
185+
"RAWDATA = ... # 3 dots are called \"Ellipsis\" and act as placeholder\n",
161186
"\n",
162-
"def download(url):\n",
163-
" ...\n",
164-
"def process(data):\n",
187+
"def fetch_data(raw_data):\n",
165188
" ... \n",
166-
"def plot(data):\n",
167-
" ...\n",
168-
" \n",
189+
"\n",
169190
"if __name__ == \"__main__\":\n",
170-
" print(\"I am running as a script\") \n",
171-
" def script_func():\n",
172-
" ...\n",
191+
" print(\"Fetching data\") \n",
192+
" data = fetch_data(RAWDATA)\n",
193+
" print(data)\n",
194+
"```\n",
195+
"\n",
196+
"```python\n",
197+
"# preprocessing.py\n",
198+
"\n",
199+
"def cleanup(data):\n",
200+
" ... \n",
173201
" \n",
174-
"```"
202+
"def preprocess_pipeline(raw_data):\n",
203+
" data = fetch_data(raw_data)\n",
204+
" return cleanup(data)\n",
205+
" \n",
206+
"if __name__ == \"__main__\":\n",
207+
" print(\"Running preprocessing\") \n",
208+
" raw_data = ...\n",
209+
" preprocess_pipeline(raw_data)\n",
210+
"```\n",
211+
"\n",
212+
"\n",
213+
"1) Copy the `RAWDATA` from the previous lab exercises into a file `data.py`\n",
214+
"2) Create another file called `preprocessing.py` in the same directory.\n",
215+
"3) Import the `RAWDATA` string inside `preprocessing.py`\n",
216+
"4) Run `data.py` as a script with `uv run src/pycourse/data.py`. Pay attention to the printed output\n",
217+
"5) Run preprocessing as a script with `uv run src/pycourse/preprocessing.py`. Pay attention to the printed output. What difference do you see compared to the previous point?"
175218
]
176219
},
177220
{
178221
"cell_type": "markdown",
179-
"id": "ee8413b5-b03f-456f-8298-a82feda2b076",
222+
"id": "1add3a63-5817-4a9c-bfcb-d041ab25eb79",
180223
"metadata": {},
181224
"source": [
182-
"## Exercises\n",
183-
"1) Copy the content of the code above into a file `data.py` and run it\n",
184-
"2) Create another file called `analysis.py` right next to `data.py` (in the same directory)\n",
185-
"3) Inside `analysis.py` import `download` from `data.py` and run `analysis.py`\n",
186-
"4) Inside `analysis.py` import `script_func` from `data.py` and run `analysis.py`. Do you understand what happens?"
225+
"Congratulations! You just ran your first python scripts 🚀"
187226
]
188227
}
189228
],
@@ -203,7 +242,7 @@
203242
"name": "python",
204243
"nbconvert_exporter": "python",
205244
"pygments_lexer": "ipython3",
206-
"version": "3.10.13"
245+
"version": "3.13.3"
207246
}
208247
},
209248
"nbformat": 4,

book/_quarto.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ book:
3838
- 03_1_flow_control.ipynb
3939
- 03_2_error_handling.ipynb
4040
- 04_functions.ipynb
41-
- 041_scope.ipynb
41+
# - 041_scope.ipynb
4242
- 05_comprehensions.ipynb
43-
- lab_syntax.ipynb
43+
- lab_builtin_for_the_win.ipynb
4444
- 06_imports.ipynb
4545
- 061_dependencies.ipynb
4646
- 062_read_and_write.ipynb
Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"outputs": [],
2828
"source": [
2929
"#| code-fold: true\n",
30-
"data = \"\"\"\\\n",
30+
"RAWDATA = \"\"\"\\\n",
3131
"onset\tduration\ttrial_type\trewards\n",
3232
"13\t0\toptions_partner\t n/a\n",
3333
"16\t0\tdecision_risky_partner\t 25\n",
@@ -247,11 +247,11 @@
247247
"id": "e5d96dc1-20b0-4a94-bdca-82be982261cd",
248248
"metadata": {},
249249
"source": [
250-
"a) Copy the data into a python file\n",
251-
"b) Traverse and print the lines. Hint: Look at strings methods\n",
252-
"c) Make a list of all the lines\n",
253-
"d) Split each line into a tuple of 4 elements (representing onset, duration, trial_type and rewards)\n",
254-
"e) Do the same but with dictionaries, that is, for each line you should get a dictionary that looks like this\n",
250+
"1) Copy the data into a python file\n",
251+
"2) Traverse and print the lines. Hint: Look at strings methods\n",
252+
"3) Make a list of all the lines\n",
253+
"4) Split each line into a tuple of 4 elements (representing onset, duration, trial_type and rewards)\n",
254+
"5) Do the same but with dictionaries, that is, for each line you should get a dictionary that looks like this\n",
255255
"\n",
256256
"```python\n",
257257
"{\n",
@@ -261,15 +261,16 @@
261261
" \"rewards\": some-value,\n",
262262
"}\n",
263263
"```\n",
264-
"f) Sort the list of dictionaries according to the rewards value. \n",
265-
"g) Repeat the same but in descendant order (larger values first).\n",
266-
"h) Make a list of the unique \"trial_type\" values that appear in the data.\n",
267-
"i) Make a dictionary that counts the number of appearances of each \"trial_type\".\n",
268-
"j) Make a list of only the entries where \"trial_type\" is of type \"decision_SOMETHING\"\n",
269-
"k) Print for each line a string that follows this pattern: \n",
264+
"6) Sort the list of dictionaries according to the rewards value. \n",
265+
"7) Repeat the same but in descendant order (larger values first).\n",
266+
"8) Make a list of the unique \"trial_type\" values that appear in the data.\n",
267+
"9) Make a dictionary that counts the number of appearances of each \"trial_type\".\n",
268+
"10) Make a list of only the entries where \"trial_type\" is of type \"decision_SOMETHING\"\n",
269+
"11) Print for each line a string that follows this pattern: \n",
270270
"```python\n",
271271
"\"For the trial type: <TRIAL-TYPE> the reward is <REWARD-VALUE>\"\n",
272-
"```"
272+
"```\n",
273+
"12) Write a function called `cleanup` that takes the raw input string and returns a list of dictionaries (like exercise item 5)"
273274
]
274275
},
275276
{

0 commit comments

Comments
 (0)