mdeck 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +259 -0
- package/LICENSE +21 -0
- package/README.md +156 -0
- package/assets/base.css +196 -0
- package/assets/extensions/layouts/chapter/extension.toml +26 -0
- package/assets/extensions/layouts/chapter/layout.jsx +21 -0
- package/assets/extensions/layouts/chapter/starter.md +8 -0
- package/assets/extensions/layouts/focus/extension.toml +8 -0
- package/assets/extensions/layouts/focus/layout.jsx +10 -0
- package/assets/extensions/layouts/focus/starter.md +4 -0
- package/assets/extensions/layouts/full-bleed-image/extension.toml +31 -0
- package/assets/extensions/layouts/full-bleed-image/layout.jsx +19 -0
- package/assets/extensions/layouts/full-bleed-image/starter.md +6 -0
- package/assets/extensions/layouts/generic/extension.toml +8 -0
- package/assets/extensions/layouts/generic/layout.jsx +8 -0
- package/assets/extensions/layouts/generic/starter.md +4 -0
- package/assets/extensions/layouts/image-text/extension.toml +25 -0
- package/assets/extensions/layouts/image-text/layout.jsx +17 -0
- package/assets/extensions/layouts/image-text/starter.md +6 -0
- package/assets/extensions/layouts/split/extension.toml +25 -0
- package/assets/extensions/layouts/split/layout.jsx +19 -0
- package/assets/extensions/layouts/split/starter.md +14 -0
- package/assets/extensions/layouts/title/extension.toml +26 -0
- package/assets/extensions/layouts/title/layout.jsx +14 -0
- package/assets/extensions/layouts/title/starter.md +5 -0
- package/assets/extensions/palettes/brand/extension.toml +29 -0
- package/assets/extensions/palettes/cobalt/extension.toml +27 -0
- package/assets/extensions/palettes/ember/extension.toml +27 -0
- package/assets/extensions/palettes/forest/extension.toml +27 -0
- package/assets/extensions/palettes/graphite/extension.toml +27 -0
- package/assets/extensions/palettes/lagoon/extension.toml +27 -0
- package/assets/extensions/palettes/neon/extension.toml +27 -0
- package/assets/extensions/palettes/nordic/extension.toml +27 -0
- package/assets/extensions/palettes/pastel/extension.toml +30 -0
- package/assets/extensions/palettes/phosphor/extension.toml +27 -0
- package/assets/extensions/palettes/swiss/extension.toml +27 -0
- package/assets/extensions/palettes/terra/extension.toml +27 -0
- package/assets/extensions/themes/academic/extension.toml +53 -0
- package/assets/extensions/themes/academic/styles.css +631 -0
- package/assets/extensions/themes/aurora/extension.toml +37 -0
- package/assets/extensions/themes/aurora/styles.css +644 -0
- package/assets/extensions/themes/duet/extension.toml +46 -0
- package/assets/extensions/themes/duet/styles.css +573 -0
- package/assets/extensions/themes/editorial/extension.toml +46 -0
- package/assets/extensions/themes/editorial/styles.css +574 -0
- package/assets/extensions/themes/fhnw/extension.toml +61 -0
- package/assets/extensions/themes/fhnw/styles.css +604 -0
- package/assets/extensions/themes/neue/extension.toml +46 -0
- package/assets/extensions/themes/neue/styles.css +489 -0
- package/assets/extensions/themes/sketch/extension.toml +48 -0
- package/assets/extensions/themes/sketch/styles.css +633 -0
- package/assets/extensions/themes/terminal/extension.toml +38 -0
- package/assets/extensions/themes/terminal/styles.css +550 -0
- package/assets/logo/avatar.png +0 -0
- package/assets/logo/logo-dark.svg +10 -0
- package/assets/logo/logo-light.svg +10 -0
- package/assets/logo/mark.svg +15 -0
- package/bin/mdeck.js +2 -0
- package/docs/README.md +8 -0
- package/docs/reference/authoring.md +795 -0
- package/docs/reference/claude-skill.md +96 -0
- package/docs/reference/extensions.md +250 -0
- package/docs/reference/layouts.md +153 -0
- package/docs/reference/palettes.md +106 -0
- package/docs/reference/structured-slides.md +120 -0
- package/docs/reference/themes.md +133 -0
- package/docs/site/assets/favicon.svg +15 -0
- package/docs/site/assets/github-logo.svg +1 -0
- package/docs/site/assets/site.css +162 -0
- package/docs/site/assets/site.js +123 -0
- package/docs/site/build.js +148 -0
- package/docs/site/content/appearance.md +203 -0
- package/docs/site/content/audience.md +178 -0
- package/docs/site/content/commands.md +153 -0
- package/docs/site/content/components.md +134 -0
- package/docs/site/content/drawing.md +72 -0
- package/docs/site/content/editing.md +59 -0
- package/docs/site/content/getting-started.md +103 -0
- package/docs/site/content/layouts.md +126 -0
- package/docs/site/content/media.md +107 -0
- package/docs/site/content/more-content.md +130 -0
- package/docs/site/content/presenting.md +93 -0
- package/docs/site/content/reusable-layouts.md +74 -0
- package/docs/site/content/sharing.md +88 -0
- package/docs/site/content/theme-authoring.md +144 -0
- package/docs/site/content/theme-repository.md +76 -0
- package/docs/site/content/troubleshooting.md +92 -0
- package/docs/site/content/views.md +56 -0
- package/docs/site/content/welcome.md +71 -0
- package/docs/site/content/writing.md +121 -0
- package/docs/site/examples/first-talk.md +88 -0
- package/docs/site/examples/notebook.svg +58 -0
- package/docs/site/images/themes/academic-dark.webp +0 -0
- package/docs/site/images/themes/academic-light.webp +0 -0
- package/docs/site/images/themes/academic.webp +0 -0
- package/docs/site/images/themes/aurora-dark.webp +0 -0
- package/docs/site/images/themes/aurora-light.webp +0 -0
- package/docs/site/images/themes/aurora.webp +0 -0
- package/docs/site/images/themes/duet-dark.webp +0 -0
- package/docs/site/images/themes/duet-light.webp +0 -0
- package/docs/site/images/themes/duet.webp +0 -0
- package/docs/site/images/themes/editorial-dark.webp +0 -0
- package/docs/site/images/themes/editorial-light.webp +0 -0
- package/docs/site/images/themes/editorial.webp +0 -0
- package/docs/site/images/themes/fhnw.webp +0 -0
- package/docs/site/images/themes/neue-dark.webp +0 -0
- package/docs/site/images/themes/neue-light.webp +0 -0
- package/docs/site/images/themes/neue.webp +0 -0
- package/docs/site/images/themes/sketch-dark.webp +0 -0
- package/docs/site/images/themes/sketch-light.webp +0 -0
- package/docs/site/images/themes/sketch.webp +0 -0
- package/docs/site/images/themes/terminal-dark.webp +0 -0
- package/docs/site/images/themes/terminal-light.webp +0 -0
- package/docs/site/images/themes/terminal.webp +0 -0
- package/docs/site/package.json +9 -0
- package/docs/site/pages.js +27 -0
- package/docs/site/server.js +58 -0
- package/examples/custom-layouts/extensions/comparison/extension.toml +35 -0
- package/examples/custom-layouts/extensions/comparison/layout.jsx +15 -0
- package/examples/custom-layouts/extensions/comparison/starter.md +17 -0
- package/examples/custom-layouts/extensions/comparison/styles.css +4 -0
- package/examples/custom-layouts/slides.md +60 -0
- package/examples/poll/slides.md +127 -0
- package/examples/python/.mdeck-backups/slides.drawings-2026-10-06T08-36-47Z.json +19 -0
- package/examples/python/.mdeck-backups/slides.drawings-2026-10-06T11-27-30Z.json +6 -0
- package/examples/python/slides.drawings.json +6 -0
- package/examples/python/slides.md +493 -0
- package/examples/showcase/.mdeck-backups/slides.drawings-2026-10-06T08-08-30Z.json +10 -0
- package/examples/showcase/.mdeck-backups/slides.drawings-2026-10-06T11-41-35Z.json +13 -0
- package/examples/showcase/img/image.jpg +0 -0
- package/examples/showcase/img/mdeck.svg +66 -0
- package/examples/showcase/slides.drawings.json +11 -0
- package/examples/showcase/slides.md +427 -0
- package/package.json +75 -0
- package/skills/write-slides/SKILL.md +144 -0
- package/src/build/check.js +49 -0
- package/src/build/chrome.js +130 -0
- package/src/build/components.js +44 -0
- package/src/build/config.js +61 -0
- package/src/build/drawings.js +14 -0
- package/src/build/editorPlugin.js +272 -0
- package/src/build/editorServer.js +36 -0
- package/src/build/fonts.js +84 -0
- package/src/build/homePlugin.js +208 -0
- package/src/build/inkPlugin.js +192 -0
- package/src/build/ownWrites.js +18 -0
- package/src/build/pairing.js +81 -0
- package/src/build/pdf.js +34 -0
- package/src/build/relayAccess.js +85 -0
- package/src/build/slidesPlugin.js +371 -0
- package/src/build/themeCheck.js +151 -0
- package/src/build/tunnelClient.js +184 -0
- package/src/cli/args.js +76 -0
- package/src/cli/index.js +758 -0
- package/src/cli/migrate.js +123 -0
- package/src/cli/skill.js +40 -0
- package/src/cli/themes.js +140 -0
- package/src/components/CodeBlock.jsx +168 -0
- package/src/components/ConnectedViews.jsx +25 -0
- package/src/components/Icon.jsx +8 -0
- package/src/components/Poll.jsx +67 -0
- package/src/components/QrCode.jsx +29 -0
- package/src/components/QrCodeTag.jsx +27 -0
- package/src/components/Question.jsx +28 -0
- package/src/components/Scale.jsx +47 -0
- package/src/components/VideoPlayer.jsx +108 -0
- package/src/components/WordCloud.jsx +106 -0
- package/src/components/activity.jsx +35 -0
- package/src/components/callout.css +78 -0
- package/src/components/code-block.css +123 -0
- package/src/components/columns.css +11 -0
- package/src/components/poll.css +81 -0
- package/src/components/video-player.css +14 -0
- package/src/core/devPath.js +4 -0
- package/src/core/editDeck.js +230 -0
- package/src/core/icons.js +69 -0
- package/src/core/ink.js +221 -0
- package/src/core/labels.js +144 -0
- package/src/core/outline.js +33 -0
- package/src/core/parseSlides.js +152 -0
- package/src/core/source.js +137 -0
- package/src/core/urls.js +34 -0
- package/src/core/validateDeck.js +139 -0
- package/src/editor/api.js +67 -0
- package/src/editor/components/App.jsx +75 -0
- package/src/editor/components/ConflictBanner.jsx +10 -0
- package/src/editor/components/DeckSettings.jsx +108 -0
- package/src/editor/components/DesignApp.jsx +252 -0
- package/src/editor/components/Diagnostics.jsx +10 -0
- package/src/editor/components/ExtensionEditor.jsx +66 -0
- package/src/editor/components/ExtensionForms.jsx +134 -0
- package/src/editor/components/ExtensionsPanel.jsx +114 -0
- package/src/editor/components/Field.jsx +24 -0
- package/src/editor/components/Inspector.jsx +36 -0
- package/src/editor/components/LayoutPicker.jsx +23 -0
- package/src/editor/components/LayoutSelect.jsx +25 -0
- package/src/editor/components/LookThumbnail.jsx +8 -0
- package/src/editor/components/MetaFields.jsx +24 -0
- package/src/editor/components/Outline.jsx +28 -0
- package/src/editor/components/PalettePicker.jsx +32 -0
- package/src/editor/components/Preview.jsx +63 -0
- package/src/editor/components/PropsForm.jsx +46 -0
- package/src/editor/components/RawSlideEditor.jsx +9 -0
- package/src/editor/components/RegionEditor.jsx +15 -0
- package/src/editor/components/Resizer.jsx +18 -0
- package/src/editor/designLink.js +19 -0
- package/src/editor/editor.css +139 -0
- package/src/editor/extensions.js +86 -0
- package/src/editor/keyboard.js +21 -0
- package/src/editor/model.js +38 -0
- package/src/editor/sampleDeck.js +165 -0
- package/src/editor/saveQueue.js +47 -0
- package/src/editor/schema.js +36 -0
- package/src/editor/state.js +92 -0
- package/src/editor/useDeckDocument.js +67 -0
- package/src/extensions/appearance.js +79 -0
- package/src/extensions/contrast.js +57 -0
- package/src/extensions/discover.js +126 -0
- package/src/extensions/manifest.js +209 -0
- package/src/extensions/packs.js +268 -0
- package/src/extensions/tokens.js +25 -0
- package/src/home/Home.jsx +362 -0
- package/src/home/home.css +148 -0
- package/src/layouts/layoutApi.jsx +205 -0
- package/src/layouts/layoutProps.js +30 -0
- package/src/layouts/renderSlide.jsx +17 -0
- package/src/live/answer/answer.css +34 -0
- package/src/live/answer/answer.html +14 -0
- package/src/live/answer/answer.js +130 -0
- package/src/live/client.js +290 -0
- package/src/live/code.js +19 -0
- package/src/live/follow.js +17 -0
- package/src/live/pairing.js +34 -0
- package/src/live/presence.js +33 -0
- package/src/live/roomTag.js +38 -0
- package/src/live/rooms.js +249 -0
- package/src/live/server.js +82 -0
- package/src/live/tunnel.js +180 -0
- package/src/paths.js +9 -0
- package/src/runtime/ReaderView.jsx +193 -0
- package/src/runtime/SlideErrorBoundary.jsx +28 -0
- package/src/runtime/chrome.jsx +55 -0
- package/src/runtime/deck-stage.js +1533 -0
- package/src/runtime/design.html +12 -0
- package/src/runtime/design.jsx +5 -0
- package/src/runtime/editor.html +12 -0
- package/src/runtime/editor.jsx +5 -0
- package/src/runtime/editorBridge.js +58 -0
- package/src/runtime/fit.js +149 -0
- package/src/runtime/home.html +13 -0
- package/src/runtime/home.jsx +5 -0
- package/src/runtime/index.html +15 -0
- package/src/runtime/ink/InkLayer.jsx +17 -0
- package/src/runtime/ink/Toolbar.jsx +145 -0
- package/src/runtime/ink/attach.js +69 -0
- package/src/runtime/ink/bus.js +126 -0
- package/src/runtime/ink/controller.js +132 -0
- package/src/runtime/ink/room.js +101 -0
- package/src/runtime/ink/select.js +124 -0
- package/src/runtime/ink/server.js +75 -0
- package/src/runtime/ink/store.js +55 -0
- package/src/runtime/ink/toolbar.css +79 -0
- package/src/runtime/main.jsx +863 -0
- package/src/runtime/markedSetup.js +147 -0
- package/src/runtime/reader.css +59 -0
- package/src/runtime/registry.jsx +26 -0
- package/src/runtime/syncOrder.js +32 -0
- package/src/runtime/themeLoader.js +68 -0
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
---
|
|
2
|
+
theme: sketch
|
|
3
|
+
meta:
|
|
4
|
+
title: "Introduction to Python"
|
|
5
|
+
author: "Tilman Schieber"
|
|
6
|
+
organization: "FHNW"
|
|
7
|
+
date: "2026-05-19"
|
|
8
|
+
palette: graphite
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
:::meta
|
|
13
|
+
layout: title
|
|
14
|
+
id: python-for-life-sciences
|
|
15
|
+
:::
|
|
16
|
+
# Python for Life Sciences.
|
|
17
|
+
## A step-by-step introduction for Master's students.
|
|
18
|
+
|
|
19
|
+
:::notes
|
|
20
|
+
Welcome to the Python module. This session assumes no prior programming experience.
|
|
21
|
+
|
|
22
|
+
- We'll move step by step — don't hesitate to interrupt with questions
|
|
23
|
+
- All code runs live in the browser — no installation needed today
|
|
24
|
+
- Goal: by the end you'll be able to load, inspect, and plot a dataset
|
|
25
|
+
:::
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
:::meta
|
|
29
|
+
layout: focus
|
|
30
|
+
eyebrow: Why Python?
|
|
31
|
+
id: the-tools-your-field-uses-are-written-in
|
|
32
|
+
:::
|
|
33
|
+
# The tools your field uses are *written in Python*.
|
|
34
|
+
|
|
35
|
+
:::notes
|
|
36
|
+
Python is the dominant language in both academia and industry for data-heavy work.
|
|
37
|
+
Life sciences is no exception — bioinformatics, imaging, and clinical data analysis all run on Python.
|
|
38
|
+
|
|
39
|
+
The ecosystem (NumPy, Pandas, Matplotlib, scikit-learn, BioPython) is unmatched.
|
|
40
|
+
Point out that R is still common in statistics, but Python has largely converged as the lingua franca.
|
|
41
|
+
:::
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
:::meta
|
|
45
|
+
layout: chapter
|
|
46
|
+
number: 1
|
|
47
|
+
part: Getting Started
|
|
48
|
+
description: Variables, types, and your first lines of code.
|
|
49
|
+
id: variables-and-data-types
|
|
50
|
+
:::
|
|
51
|
+
# Variables and data types.
|
|
52
|
+
|
|
53
|
+
:::notes
|
|
54
|
+
Start here even if students have seen some Python before. We build from the ground up.
|
|
55
|
+
Estimated time for this chapter: 20 minutes.
|
|
56
|
+
:::
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
:::meta
|
|
60
|
+
layout: split
|
|
61
|
+
section: Variables
|
|
62
|
+
id: variables-store-data
|
|
63
|
+
props:
|
|
64
|
+
ratio: [3, 2]
|
|
65
|
+
:::
|
|
66
|
+
# A variable is a name for a value.
|
|
67
|
+
:::slot left
|
|
68
|
+
```python live editable copy
|
|
69
|
+
name = "E. coli"
|
|
70
|
+
genome_size = 4_641_652 # base pairs
|
|
71
|
+
gc_content = 0.506 # fraction
|
|
72
|
+
|
|
73
|
+
print(name, genome_size, gc_content)
|
|
74
|
+
print(f"GC content: {gc_content:.1%}")
|
|
75
|
+
```
|
|
76
|
+
:::
|
|
77
|
+
:::slot right
|
|
78
|
+
No declarations: Python sees the type from the value.
|
|
79
|
+
|
|
80
|
+
**Try it:** change `gc_content` to `0.65` and run again.
|
|
81
|
+
:::
|
|
82
|
+
|
|
83
|
+
:::notes
|
|
84
|
+
A variable is just a name attached to a value. Python figures out the type automatically.
|
|
85
|
+
|
|
86
|
+
Point out: no semicolons, no type declarations, no boilerplate. The `f"…"` string formats a value inside text; `:.1%` shows a fraction as a percentage.
|
|
87
|
+
Encourage students to change the values and re-run — that's the point of the live block.
|
|
88
|
+
:::
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
:::meta
|
|
92
|
+
section: Data Types
|
|
93
|
+
id: four-types-cover-most-biology-data
|
|
94
|
+
:::
|
|
95
|
+
# Four types cover most biology data.
|
|
96
|
+
|
|
97
|
+
:::steps
|
|
98
|
+
- **`int`** — whole numbers: counts, positions, indices
|
|
99
|
+
- **`float`** — decimals: concentrations, p-values, fold changes
|
|
100
|
+
- **`str`** — text: gene names, sequences, sample IDs
|
|
101
|
+
- **`bool`** — True or False: significance flags, quality filters
|
|
102
|
+
:::
|
|
103
|
+
|
|
104
|
+
:::notes
|
|
105
|
+
Reveal one type at a time and ask for an example from the lab before showing the next.
|
|
106
|
+
|
|
107
|
+
Emphasise that booleans typically come from comparisons, not literal True/False. The next slide asks the room.
|
|
108
|
+
:::
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
:::meta
|
|
112
|
+
section: Data Types
|
|
113
|
+
title: "Poll: the type of a p-value"
|
|
114
|
+
id: poll-the-type-of-a-p-value
|
|
115
|
+
:::
|
|
116
|
+
# What type is a p-value?
|
|
117
|
+
|
|
118
|
+
<poll room="p-value" options="int|float|str|bool" answer="float" />
|
|
119
|
+
|
|
120
|
+
:::notes
|
|
121
|
+
A quick check before moving on. Phones join with the QR code; start the deck with `mdeck run slides.md --network` so they can reach this computer.
|
|
122
|
+
|
|
123
|
+
Answer: `float`; the tick button under the bars marks it. If many chose `bool`, they are thinking of the *significance flag* computed from it (`p < 0.05`): a good moment to show that comparisons produce booleans.
|
|
124
|
+
:::
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
:::meta
|
|
128
|
+
layout: split
|
|
129
|
+
section: Strings
|
|
130
|
+
props:
|
|
131
|
+
ratio: [3, 2]
|
|
132
|
+
:::
|
|
133
|
+
# Strings behave like sequences.
|
|
134
|
+
:::slot left
|
|
135
|
+
```python live editable copy
|
|
136
|
+
dna = "ATGCGTAAGCTTGAC"
|
|
137
|
+
|
|
138
|
+
print("Length: ", len(dna))
|
|
139
|
+
print("First codon:", dna[:3])
|
|
140
|
+
print("A count: ", dna.count("A"))
|
|
141
|
+
print("Reversed: ", dna[::-1])
|
|
142
|
+
print("As RNA: ", dna.replace("T", "U"))
|
|
143
|
+
```
|
|
144
|
+
:::
|
|
145
|
+
:::slot right
|
|
146
|
+
Slicing, counting and replacing work the same on any text.
|
|
147
|
+
|
|
148
|
+
**Try it:** print the last codon with `dna[-3:]`.
|
|
149
|
+
:::
|
|
150
|
+
|
|
151
|
+
:::notes
|
|
152
|
+
Strings are sequences — you can slice them just like a nucleotide sequence.
|
|
153
|
+
`replace("T", "U")` is transcription in one line. The concepts transfer directly to BioPython later.
|
|
154
|
+
:::
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
:::meta
|
|
158
|
+
layout: chapter
|
|
159
|
+
number: 2
|
|
160
|
+
part: Collections
|
|
161
|
+
description: Storing and accessing multiple values at once.
|
|
162
|
+
:::
|
|
163
|
+
# Lists and dictionaries.
|
|
164
|
+
|
|
165
|
+
:::notes
|
|
166
|
+
Most real data is not a single value. Lists and dictionaries are the two workhorse collections.
|
|
167
|
+
Estimated time for this chapter: 25 minutes.
|
|
168
|
+
:::
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
:::meta
|
|
172
|
+
layout: split
|
|
173
|
+
section: Lists
|
|
174
|
+
props:
|
|
175
|
+
ratio: [3, 2]
|
|
176
|
+
:::
|
|
177
|
+
# A list holds values in order.
|
|
178
|
+
:::slot left
|
|
179
|
+
```python live editable copy
|
|
180
|
+
conc = [0.12, 0.45, 0.33, 0.78, 0.21]
|
|
181
|
+
|
|
182
|
+
print("Samples:", len(conc))
|
|
183
|
+
print("First: ", conc[0])
|
|
184
|
+
print("Last: ", conc[-1])
|
|
185
|
+
print("Sorted: ", sorted(conc))
|
|
186
|
+
print("Mean: ", sum(conc) / len(conc))
|
|
187
|
+
```
|
|
188
|
+
:::
|
|
189
|
+
:::slot right
|
|
190
|
+
Counting starts at zero: `conc[0]` is the first item, `conc[-1]` the last.
|
|
191
|
+
|
|
192
|
+
**Try it:** add a sixth value and watch the mean change.
|
|
193
|
+
:::
|
|
194
|
+
|
|
195
|
+
:::notes
|
|
196
|
+
Lists maintain order and allow duplicates. Index from 0. Negative indices count from the end.
|
|
197
|
+
Great for: time series, replicate measurements, ordered processing steps.
|
|
198
|
+
|
|
199
|
+
Common mistake: students try index 1 for the first element. Drill 0-indexing early.
|
|
200
|
+
:::
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
:::meta
|
|
204
|
+
layout: split
|
|
205
|
+
section: Dictionaries
|
|
206
|
+
props:
|
|
207
|
+
ratio: [3, 2]
|
|
208
|
+
:::
|
|
209
|
+
# A dictionary looks values up by name.
|
|
210
|
+
:::slot left
|
|
211
|
+
```python live editable copy
|
|
212
|
+
sample = {
|
|
213
|
+
"id": "S042",
|
|
214
|
+
"organism": "Mus musculus",
|
|
215
|
+
"tissue": "liver",
|
|
216
|
+
"weight_mg": 312,
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
print(sample["organism"])
|
|
220
|
+
sample["weight_mg"] = 318 # update a field
|
|
221
|
+
print(sample)
|
|
222
|
+
```
|
|
223
|
+
:::
|
|
224
|
+
:::slot right
|
|
225
|
+
One dictionary describes one sample: no column numbers to remember.
|
|
226
|
+
|
|
227
|
+
**Try it:** add `"treated": True`.
|
|
228
|
+
:::
|
|
229
|
+
|
|
230
|
+
:::notes
|
|
231
|
+
Dictionaries map keys to values. Perfect for structured records — one dictionary = one sample.
|
|
232
|
+
Later, a list of dictionaries becomes a Pandas DataFrame. Plant that seed now.
|
|
233
|
+
:::
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
:::meta
|
|
237
|
+
layout: chapter
|
|
238
|
+
number: 3
|
|
239
|
+
part: Control Flow
|
|
240
|
+
description: Making decisions and repeating operations across your data.
|
|
241
|
+
:::
|
|
242
|
+
# Decisions and loops.
|
|
243
|
+
|
|
244
|
+
:::notes
|
|
245
|
+
These two constructs — if and for — cover the vast majority of logic in data processing scripts.
|
|
246
|
+
Estimated time for this chapter: 25 minutes.
|
|
247
|
+
:::
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
:::meta
|
|
251
|
+
layout: split
|
|
252
|
+
section: Conditions
|
|
253
|
+
props:
|
|
254
|
+
ratio: [3, 2]
|
|
255
|
+
:::
|
|
256
|
+
# `if` chooses a path.
|
|
257
|
+
:::slot left
|
|
258
|
+
```python live editable copy
|
|
259
|
+
p_value = 0.023
|
|
260
|
+
fold_change = 2.4
|
|
261
|
+
|
|
262
|
+
if p_value < 0.05 and fold_change > 2:
|
|
263
|
+
print("Significant upregulation")
|
|
264
|
+
elif p_value < 0.05:
|
|
265
|
+
print("Significant, modest effect")
|
|
266
|
+
else:
|
|
267
|
+
print("Not significant")
|
|
268
|
+
```
|
|
269
|
+
:::
|
|
270
|
+
:::slot right
|
|
271
|
+
The indentation is the block: Python uses whitespace, not braces.
|
|
272
|
+
|
|
273
|
+
**Try it:** set `fold_change = 1.5`.
|
|
274
|
+
:::
|
|
275
|
+
|
|
276
|
+
:::notes
|
|
277
|
+
if / elif / else covers all branching. Indentation is not stylistic in Python — it is syntax.
|
|
278
|
+
This trips up students from other languages or R. The colon and the indent are mandatory.
|
|
279
|
+
Show what happens if you forget the colon: Python gives a SyntaxError.
|
|
280
|
+
:::
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
:::meta
|
|
284
|
+
layout: split
|
|
285
|
+
section: Loops
|
|
286
|
+
props:
|
|
287
|
+
ratio: [3, 2]
|
|
288
|
+
:::
|
|
289
|
+
# `for` repeats an action for every item.
|
|
290
|
+
:::slot left
|
|
291
|
+
```python live editable copy
|
|
292
|
+
values = [1.2, 0.8, 2.1, 1.5, 0.9, 2.8]
|
|
293
|
+
|
|
294
|
+
above = []
|
|
295
|
+
for value in values:
|
|
296
|
+
if value > 1.0:
|
|
297
|
+
above.append(value)
|
|
298
|
+
|
|
299
|
+
print(len(above), "of", len(values))
|
|
300
|
+
print(above)
|
|
301
|
+
```
|
|
302
|
+
:::
|
|
303
|
+
:::slot right
|
|
304
|
+
Loop, test, collect: the core pattern of filtering data.
|
|
305
|
+
|
|
306
|
+
**Try it:** count the values below 1.0 instead.
|
|
307
|
+
:::
|
|
308
|
+
|
|
309
|
+
:::notes
|
|
310
|
+
for loops iterate over any collection. This pattern — loop, test, collect — is at the heart of
|
|
311
|
+
almost every data processing script students will write.
|
|
312
|
+
|
|
313
|
+
Press **D** and trace one value through the loop on the slide: into `value`, through the `if`, into `above`. Escape stops drawing; the drawing stays with the slide.
|
|
314
|
+
:::
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
:::meta
|
|
318
|
+
layout: chapter
|
|
319
|
+
number: 4
|
|
320
|
+
part: Functions
|
|
321
|
+
description: Packaging logic so you can reuse and test it.
|
|
322
|
+
:::
|
|
323
|
+
# Functions package logic for reuse.
|
|
324
|
+
|
|
325
|
+
:::notes
|
|
326
|
+
Functions are the first step toward reusable, testable code.
|
|
327
|
+
Motivate with: "you'll run this same calculation on 200 samples — write it once, call it 200 times."
|
|
328
|
+
Estimated time for this chapter: 20 minutes.
|
|
329
|
+
:::
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
:::meta
|
|
333
|
+
layout: split
|
|
334
|
+
section: Functions
|
|
335
|
+
props:
|
|
336
|
+
ratio: [3, 2]
|
|
337
|
+
:::
|
|
338
|
+
# A function turns inputs into an output.
|
|
339
|
+
:::slot left
|
|
340
|
+
```python live editable copy
|
|
341
|
+
def gc_content(seq):
|
|
342
|
+
"""Return the GC fraction of a sequence."""
|
|
343
|
+
gc = seq.count("G") + seq.count("C")
|
|
344
|
+
return gc / len(seq)
|
|
345
|
+
|
|
346
|
+
for seq in ["ATGCGC", "AATTAA", "GCGCGC"]:
|
|
347
|
+
print(seq, f"{gc_content(seq):.0%}")
|
|
348
|
+
```
|
|
349
|
+
:::
|
|
350
|
+
:::slot right
|
|
351
|
+
Write it once, then call it on every sample.
|
|
352
|
+
|
|
353
|
+
**Try it:** add your own sequence to the list.
|
|
354
|
+
:::
|
|
355
|
+
|
|
356
|
+
:::notes
|
|
357
|
+
def, parameters, return — that's the whole syntax.
|
|
358
|
+
Walk through: define once, call many times with different inputs.
|
|
359
|
+
The docstring (triple-quoted string after def) is best practice — introduce it early.
|
|
360
|
+
:::
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
:::meta
|
|
364
|
+
layout: chapter
|
|
365
|
+
number: 5
|
|
366
|
+
part: Scientific Python
|
|
367
|
+
description: NumPy, Pandas, and Matplotlib — the three pillars.
|
|
368
|
+
:::
|
|
369
|
+
# The scientific stack.
|
|
370
|
+
|
|
371
|
+
:::notes
|
|
372
|
+
These three libraries are what make Python the dominant language in data science.
|
|
373
|
+
Students won't write much pure Python in practice — they'll use these.
|
|
374
|
+
Estimated time for this chapter: 30 minutes.
|
|
375
|
+
:::
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
:::meta
|
|
379
|
+
section: Scientific Python
|
|
380
|
+
:::
|
|
381
|
+
# Three libraries cover most life sciences workflows.
|
|
382
|
+
|
|
383
|
+
:::steps
|
|
384
|
+
- **NumPy** — fast arrays: calculate on a whole dataset at once
|
|
385
|
+
- **Pandas** — tables: load, filter, group and summarise spreadsheet data
|
|
386
|
+
- **Matplotlib** — plots, with control over every element
|
|
387
|
+
:::
|
|
388
|
+
|
|
389
|
+
:::notes
|
|
390
|
+
Brief overview before diving in. The key message: these libraries handle the heavy lifting
|
|
391
|
+
so students write less code and get faster, more reliable results than with pure Python loops.
|
|
392
|
+
:::
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
:::meta
|
|
396
|
+
layout: split
|
|
397
|
+
section: NumPy
|
|
398
|
+
props:
|
|
399
|
+
ratio: [3, 2]
|
|
400
|
+
:::
|
|
401
|
+
# NumPy calculates on whole arrays.
|
|
402
|
+
:::slot left
|
|
403
|
+
```python live copy
|
|
404
|
+
import numpy as np
|
|
405
|
+
|
|
406
|
+
m = np.array([1.2, 0.8, 2.1, 1.5, 0.9, 2.8])
|
|
407
|
+
|
|
408
|
+
print("Mean: ", m.mean().round(3))
|
|
409
|
+
print("Std: ", m.std().round(3))
|
|
410
|
+
print("Median:", np.median(m))
|
|
411
|
+
print("> 1.5: ", m[m > 1.5])
|
|
412
|
+
```
|
|
413
|
+
:::
|
|
414
|
+
:::slot right
|
|
415
|
+
`m[m > 1.5]` filters without a loop.
|
|
416
|
+
|
|
417
|
+
Compare it with the `for` loop two chapters ago.
|
|
418
|
+
:::
|
|
419
|
+
|
|
420
|
+
:::notes
|
|
421
|
+
NumPy operations apply to the whole array at once — no loops. This is both faster and more readable.
|
|
422
|
+
The vectorised style takes getting used to but is worth learning early.
|
|
423
|
+
Demo: ask students to predict what `m > 1.5` returns before running it.
|
|
424
|
+
:::
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
:::meta
|
|
428
|
+
layout: focus
|
|
429
|
+
eyebrow: Key insight
|
|
430
|
+
:::
|
|
431
|
+
# Write operations on *arrays*, not on single values.
|
|
432
|
+
|
|
433
|
+
:::notes
|
|
434
|
+
This is the most important mental model shift from pure Python to scientific Python.
|
|
435
|
+
Repeat it, let it sink in. Students who internalise this early write much cleaner code later.
|
|
436
|
+
:::
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
:::meta
|
|
440
|
+
layout: chapter
|
|
441
|
+
number: 6
|
|
442
|
+
part: Next Steps
|
|
443
|
+
description: Where to go from here.
|
|
444
|
+
id: keep-going
|
|
445
|
+
:::
|
|
446
|
+
# Keep going.
|
|
447
|
+
|
|
448
|
+
:::notes
|
|
449
|
+
Close with a roadmap. Students often feel lost after an intro — give them concrete next steps
|
|
450
|
+
and point them to the best free resources.
|
|
451
|
+
:::
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
:::meta
|
|
455
|
+
section: Next Steps
|
|
456
|
+
:::
|
|
457
|
+
# What to learn next.
|
|
458
|
+
|
|
459
|
+
- **Pandas** — load a CSV, filter rows, compute group statistics
|
|
460
|
+
- **Matplotlib and Seaborn** — scatter plots, heatmaps, volcano plots
|
|
461
|
+
- **scikit-learn** — classification, clustering, dimensionality reduction
|
|
462
|
+
- **BioPython** — sequences, BLAST, GenBank and PDB files
|
|
463
|
+
|
|
464
|
+
:::notes
|
|
465
|
+
For self-study: the official Python tutorial for syntax, Pandas documentation for data work.
|
|
466
|
+
Kaggle's free Python and Pandas courses are excellent and self-paced.
|
|
467
|
+
For life sciences specifically: BioPython docs, and the Python for Bioinformatics textbook (Bassi).
|
|
468
|
+
:::
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
:::meta
|
|
472
|
+
layout: focus
|
|
473
|
+
eyebrow: Remember
|
|
474
|
+
:::
|
|
475
|
+
# The best way to learn to code is to *write code*.
|
|
476
|
+
|
|
477
|
+
:::notes
|
|
478
|
+
Close on this. Programming is a skill — it takes practice. The first few weeks feel slow,
|
|
479
|
+
then things click. Encourage daily practice, even small scripts. Point to the exercises.
|
|
480
|
+
:::
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
:::meta
|
|
484
|
+
layout: title
|
|
485
|
+
:::
|
|
486
|
+
# Questions?
|
|
487
|
+
## Thank you — now open your laptops.
|
|
488
|
+
|
|
489
|
+
:::notes
|
|
490
|
+
Leave time for questions.
|
|
491
|
+
Remind students where to find the course materials and how to reach you.
|
|
492
|
+
The next session will cover Pandas and loading real datasets.
|
|
493
|
+
:::
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"width": 1920,
|
|
4
|
+
"height": 1080,
|
|
5
|
+
"slides": {
|
|
6
|
+
"draw-on-any-slide": [
|
|
7
|
+
{"id":"pkpb2b:muw89tng0","tool":"pen","color":"#e11d48","size":6,"points":[[1247,286,0.5]]}
|
|
8
|
+
],
|
|
9
|
+
"give-the-talk": [
|
|
10
|
+
{"id":"pkpb2b:muwectdg0","tool":"pen","color":"#e11d48","size":6,"points":[[950,358,0.5],[917,358,0.5],[899,362,0.5],[877,369,0.5],[861,381,0.5],[851,391,0.5],[845,403,0.5],[838,421,0.5],[833,439,0.5],[831,453,0.5],[831,490,0.5],[833,506,0.5],[839,517,0.5],[849,525,0.5],[868,532,0.5],[895,536,0.5],[958,537,0.5],[998,533,0.5],[1043,522,0.5],[1087,505,0.5],[1132,483,0.5],[1181,452,0.5],[1207,433,0.5],[1235,409,0.5],[1257,386,0.5],[1275,364,0.5],[1287,341,0.5],[1294,318,0.5],[1297,295,0.5],[1297,270,0.5],[1290,245,0.5],[1270,214,0.5],[1241,186,0.5],[1205,169,0.5],[1142,159,0.5],[1061,157,0.5],[975,179,0.5],[878,227,0.5],[793,283,0.5],[709,354,0.5],[637,423,0.5],[587,486,0.5],[544,556,0.5],[519,618,0.5],[508,672,0.5],[510,716,0.5],[527,752,0.5],[558,779,0.5],[601,798,0.5],[653,809,0.5],[712,812,0.5],[775,810,0.5],[843,797,0.5],[961,744,0.5],[1006,711,0.5],[1055,668,0.5],[1095,620,0.5],[1126,571,0.5],[1141,534,0.5],[1147,501,0.5],[1149,467,0.5],[1146,443,0.5],[1130,424,0.5],[1094,413,0.5],[1047,420,0.5],[995,450,0.5],[953,487,0.5],[917,531,0.5],[886,571,0.5],[872,599,0.5],[856,633,0.5],[846,662,0.5],[843,691,0.5],[844,722,0.5],[856,739,0.5],[893,745,0.5],[949,740,0.5],[1015,717,0.5],[1093,675,0.5],[1174,620,0.5],[1232,574,0.5],[1261,543,0.5],[1292,508,0.5],[1313,480,0.5],[1341,420,0.5],[1339,409,0.5],[1318,400,0.5],[1254,406,0.5],[1155,442,0.5],[1035,512,0.5],[932,585,0.5],[836,667,0.5],[758,743,0.5],[724,785,0.5],[704,814,0.5],[686,843,0.5],[666,887,0.5],[659,916,0.5],[685,915,0.5],[767,878,0.5],[884,801,0.5],[977,728,0.5],[1051,667,0.5],[1140,590,0.5],[1218,521,0.5],[1260,481,0.5],[1325,417,0.5],[1334,405,0.5],[1334,399,0.5],[1306,412,0.5],[1172,492,0.5],[1112,530,0.5],[1079,553,0.5],[1039,582,0.5],[1016,601,0.5]]}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="800" viewBox="0 0 960 800">
|
|
2
|
+
<!-- A Markdown file becoming a stack of slides. The colours come from the
|
|
3
|
+
deck's palette (var(--accent) …), so the picture follows the theme;
|
|
4
|
+
the fallbacks apply where it is shown as a plain image. -->
|
|
5
|
+
<style>
|
|
6
|
+
.mdk-paper { fill: var(--surface, #eef1fb); stroke: var(--rule, #d5dbf0); stroke-width: 3; }
|
|
7
|
+
.mdk-fold { fill: var(--rule, #d5dbf0); }
|
|
8
|
+
.mdk-shadow { fill: var(--ink, #0c1033); opacity: .12; }
|
|
9
|
+
.mdk-code { font-family: ui-monospace, 'JetBrains Mono', Menlo, Consolas, monospace; font-size: 30px; fill: var(--ink-soft, #2a2f55); }
|
|
10
|
+
.mdk-mark { fill: var(--accent, #1f3fd1); font-weight: 700; }
|
|
11
|
+
.mdk-quiet { fill: var(--muted, #5b6080); }
|
|
12
|
+
.mdk-slide { fill: var(--bg, #ffffff); stroke: var(--ink, #0c1033); stroke-width: 3; }
|
|
13
|
+
.mdk-accent { fill: var(--accent, #1f3fd1); }
|
|
14
|
+
.mdk-accent-2 { fill: var(--accent-2, #e8590c); }
|
|
15
|
+
.mdk-rule { fill: var(--rule, #d5dbf0); }
|
|
16
|
+
.mdk-on-accent { fill: var(--on-accent, #ffffff); font-family: var(--font-display, sans-serif); font-weight: 800; font-size: 96px; }
|
|
17
|
+
.mdk-title { fill: var(--ink, #0c1033); font-family: var(--font-display, sans-serif); font-weight: 800; font-size: 46px; }
|
|
18
|
+
.mdk-arrow { fill: none; stroke: var(--accent-2, #e8590c); stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
|
|
19
|
+
</style>
|
|
20
|
+
|
|
21
|
+
<!-- The text file -->
|
|
22
|
+
<g transform="rotate(-5 230 400)">
|
|
23
|
+
<rect class="mdk-shadow" x="56" y="146" width="370" height="510" rx="18"/>
|
|
24
|
+
<path class="mdk-paper" d="M58 130 h290 l62 62 v438 a18 18 0 0 1 -18 18 h-316 a18 18 0 0 1 -18 -18 v-482 a18 18 0 0 1 18 -18 z"/>
|
|
25
|
+
<path class="mdk-fold" d="M348 130 v44 a18 18 0 0 0 18 18 h44 z"/>
|
|
26
|
+
<text class="mdk-code" x="84" y="232"><tspan class="mdk-mark">#</tspan> A talk</text>
|
|
27
|
+
<text class="mdk-code" x="84" y="300"><tspan class="mdk-mark">-</tspan> one idea</text>
|
|
28
|
+
<text class="mdk-code" x="84" y="344"><tspan class="mdk-mark">-</tspan> an example</text>
|
|
29
|
+
<text class="mdk-code mdk-mark" x="84" y="412">---</text>
|
|
30
|
+
<text class="mdk-code mdk-quiet" x="84" y="480">:::notes</text>
|
|
31
|
+
<text class="mdk-code mdk-quiet" x="84" y="524">pause here</text>
|
|
32
|
+
<text class="mdk-code mdk-quiet" x="84" y="568">:::</text>
|
|
33
|
+
</g>
|
|
34
|
+
|
|
35
|
+
<!-- From text to slides -->
|
|
36
|
+
<path class="mdk-arrow" d="M300 112 C 380 20, 560 22, 640 150" stroke-dasharray="2 16"/>
|
|
37
|
+
<path class="mdk-arrow" d="M612 138 l30 16 l4 -34"/>
|
|
38
|
+
<path class="mdk-accent" d="M470 60 l7 17 l17 7 l-17 7 l-7 17 l-7 -17 l-17 -7 l17 -7 z"/>
|
|
39
|
+
<path class="mdk-accent-2" d="M760 210 l5 12 l12 5 l-12 5 l-5 12 l-5 -12 l-12 -5 l12 -5 z"/>
|
|
40
|
+
|
|
41
|
+
<!-- The slides: a chapter, a statement, and a content slide in front -->
|
|
42
|
+
<g transform="rotate(9 680 330)">
|
|
43
|
+
<rect class="mdk-accent-2" x="440" y="200" width="480" height="270" rx="14"/>
|
|
44
|
+
</g>
|
|
45
|
+
<g transform="rotate(3 660 420)">
|
|
46
|
+
<rect class="mdk-accent" x="420" y="290" width="480" height="270" rx="14"/>
|
|
47
|
+
<text class="mdk-on-accent" x="452" y="386">2</text>
|
|
48
|
+
<rect class="mdk-accent-2" x="512" y="350" width="80" height="10" rx="5"/>
|
|
49
|
+
</g>
|
|
50
|
+
<g transform="rotate(-3 640 540)">
|
|
51
|
+
<rect class="mdk-shadow" x="412" y="420" width="480" height="270" rx="14"/>
|
|
52
|
+
<rect class="mdk-slide" x="400" y="404" width="480" height="270" rx="14"/>
|
|
53
|
+
<text class="mdk-title" x="432" y="470">A talk</text>
|
|
54
|
+
<rect class="mdk-accent" x="432" y="486" width="88" height="8" rx="4"/>
|
|
55
|
+
<rect class="mdk-accent" x="432" y="524" width="14" height="14" rx="3"/>
|
|
56
|
+
<rect class="mdk-rule" x="458" y="525" width="150" height="12" rx="6"/>
|
|
57
|
+
<rect class="mdk-accent" x="432" y="562" width="14" height="14" rx="3"/>
|
|
58
|
+
<rect class="mdk-rule" x="458" y="563" width="120" height="12" rx="6"/>
|
|
59
|
+
<rect class="mdk-accent" x="432" y="600" width="14" height="14" rx="3"/>
|
|
60
|
+
<rect class="mdk-rule" x="458" y="601" width="136" height="12" rx="6"/>
|
|
61
|
+
<rect class="mdk-accent-2" x="682" y="580" width="34" height="62" rx="4"/>
|
|
62
|
+
<rect class="mdk-accent" x="726" y="530" width="34" height="112" rx="4"/>
|
|
63
|
+
<rect class="mdk-accent-2" x="770" y="556" width="34" height="86" rx="4"/>
|
|
64
|
+
<rect class="mdk-accent" x="814" y="500" width="34" height="142" rx="4"/>
|
|
65
|
+
</g>
|
|
66
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"width": 1920,
|
|
4
|
+
"height": 1080,
|
|
5
|
+
"slides": {
|
|
6
|
+
"draw-on-any-slide": [
|
|
7
|
+
{"id":"tour:underline","tool":"pen","color":"#e11d48","size":7,"points":[[120,462,0.45],[135,464,0.48],[150,466,0.52],[165,467,0.55],[180,468,0.58],[195,469,0.61],[210,469,0.64],[225,468,0.66],[240,467,0.68],[255,465,0.7],[270,464,0.72],[285,462,0.73],[300,460,0.74],[315,459,0.75],[330,458,0.75],[345,458,0.75],[360,459,0.74],[375,460,0.73],[390,461,0.72],[405,463,0.71],[420,465,0.69],[435,467,0.67],[450,469,0.64],[465,470,0.62],[480,471,0.59],[495,472,0.56],[510,472,0.53],[525,471,0.49],[540,470,0.46],[555,468,0.43],[570,467,0.39],[585,465,0.36],[600,464,0.33],[615,462,0.3],[630,462,0.27],[645,461,0.25],[660,462,0.22],[675,462,0.2],[690,464,0.19],[705,466,0.17],[720,468,0.16]]},
|
|
8
|
+
{"id":"tour:circle","tool":"pen","color":"#e11d48","size":6,"points":[[226,491,0.5],[230,491,0.54],[235,491,0.57],[239,492,0.6],[243,494,0.64],[247,497,0.66],[250,500,0.69],[252,504,0.71],[254,508,0.73],[255,512,0.74],[256,516,0.75],[255,520,0.75],[254,524,0.75],[252,528,0.74],[250,532,0.73],[247,534,0.71],[244,537,0.69],[240,539,0.66],[237,541,0.63],[233,542,0.6],[229,543,0.57],[225,543,0.54],[221,543,0.5],[217,543,0.46],[213,541,0.43],[209,540,0.4],[206,538,0.36],[203,535,0.34],[200,531,0.31],[198,528,0.29],[196,523,0.27],[196,519,0.26],[196,515,0.25],[197,510,0.25],[199,506,0.25],[201,503,0.26],[204,500,0.27],[207,497,0.29],[211,495,0.31],[215,494,0.34],[219,493,0.37],[223,493,0.4],[227,493,0.43],[231,493,0.47],[235,495,0.5],[239,496,0.54]]}
|
|
9
|
+
]
|
|
10
|
+
}
|
|
11
|
+
}
|