Update app.py

#3
by deleted - opened
Files changed (1) hide show
  1. app.py +389 -382
app.py CHANGED
@@ -1,470 +1,477 @@
1
  import marimo
2
 
3
- __generated_with = "0.9.2"
4
- app = marimo.App()
5
 
6
 
7
  @app.cell
8
- def __():
9
  import marimo as mo
10
-
11
- mo.md("# Welcome to marimo! πŸŒŠπŸƒ")
12
- return (mo,)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
 
15
  @app.cell
16
- def __(mo):
17
- slider = mo.ui.slider(1, 22)
18
- return (slider,)
 
 
 
 
19
 
20
 
21
  @app.cell
22
- def __(mo, slider):
23
- mo.md(
24
- f"""
25
- marimo is a **reactive** Python notebook.
26
 
27
- This means that unlike traditional notebooks, marimo notebooks **run
28
- automatically** when you modify them or
29
- interact with UI elements, like this slider: {slider}.
30
 
31
- {"##" + "πŸƒ" * slider.value}
32
- """
 
33
  )
34
- return
35
-
36
-
37
- @app.cell(hide_code=True)
38
- def __(mo):
39
- mo.accordion(
40
- {
41
- "Tip: disabling automatic execution": mo.md(
42
- rf"""
43
- marimo lets you disable automatic execution: just go into the
44
- notebook settings and set
45
-
46
- "Runtime > On Cell Change" to "lazy".
47
-
48
- When the runtime is lazy, after running a cell, marimo marks its
49
- descendants as stale instead of automatically running them. The
50
- lazy runtime puts you in control over when cells are run, while
51
- still giving guarantees about the notebook state.
52
- """
53
- )
54
- }
55
  )
56
- return
57
-
58
-
59
- @app.cell(hide_code=True)
60
- def __(mo):
61
- mo.md(
62
- """
63
- Tip: This is a tutorial notebook. You can create your own notebooks
64
- by entering `marimo edit` at the command line.
65
- """
66
- ).callout()
67
- return
68
-
69
 
70
- @app.cell(hide_code=True)
71
- def __(mo):
72
- mo.md(
73
- """
74
- ## 1. Reactive execution
75
 
76
- A marimo notebook is made up of small blocks of Python code called
77
- cells.
78
-
79
- marimo reads your cells and models the dependencies among them: whenever
80
- a cell that defines a global variable is run, marimo
81
- **automatically runs** all cells that reference that variable.
82
 
83
- Reactivity keeps your program state and outputs in sync with your code,
84
- making for a dynamic programming environment that prevents bugs before they
85
- happen.
86
- """
87
  )
88
  return
89
 
90
 
91
- @app.cell(hide_code=True)
92
- def __(changed, mo):
93
- (
94
- mo.md(
95
- f"""
96
- **✨ Nice!** The value of `changed` is now {changed}.
97
-
98
- When you updated the value of the variable `changed`, marimo
99
- **reacted** by running this cell automatically, because this cell
100
- references the global variable `changed`.
101
-
102
- Reactivity ensures that your notebook state is always
103
- consistent, which is crucial for doing good science; it's also what
104
- enables marimo notebooks to double as tools and apps.
105
- """
106
- )
107
- if changed
108
- else mo.md(
109
- """
110
- **🌊 See it in action.** In the next cell, change the value of the
111
- variable `changed` to `True`, then click the run button.
112
- """
113
- )
114
- )
115
- return
116
 
117
 
118
  @app.cell
119
- def __():
120
- changed = False
121
- return (changed,)
122
-
123
-
124
- @app.cell(hide_code=True)
125
- def __(mo):
126
- mo.accordion(
127
- {
128
- "Tip: execution order": (
129
- """
130
- The order of cells on the page has no bearing on
131
- the order in which cells are executed: marimo knows that a cell
132
- reading a variable must run after the cell that defines it. This
133
- frees you to organize your code in the way that makes the most
134
- sense for you.
135
- """
136
- )
137
- }
138
- )
139
- return
 
140
 
 
141
 
142
- @app.cell(hide_code=True)
143
- def __(mo):
144
- mo.md(
145
- """
146
- **Global names must be unique.** To enable reactivity, marimo imposes a
147
- constraint on how names appear in cells: no two cells may define the same
148
- variable.
149
- """
150
- )
151
- return
152
 
153
 
154
- @app.cell(hide_code=True)
155
- def __(mo):
156
- mo.accordion(
157
- {
158
- "Tip: encapsulation": (
159
- """
160
- By encapsulating logic in functions, classes, or Python modules,
161
- you can minimize the number of global variables in your notebook.
162
- """
163
- )
164
- }
165
- )
166
- return
167
 
168
 
169
- @app.cell(hide_code=True)
170
- def __(mo):
171
- mo.accordion(
172
- {
173
- "Tip: private variables": (
174
- """
175
- Variables prefixed with an underscore are "private" to a cell, so
176
- they can be defined by multiple cells.
177
- """
178
- )
179
- }
180
- )
181
- return
182
 
 
183
 
184
- @app.cell(hide_code=True)
185
- def __(mo):
186
- mo.md(
187
- """
188
- ## 2. UI elements
189
 
190
- Cells can output interactive UI elements. Interacting with a UI
191
- element **automatically triggers notebook execution**: when
192
- you interact with a UI element, its value is sent back to Python, and
193
- every cell that references that element is re-run.
 
 
 
 
 
 
194
 
195
- marimo provides a library of UI elements to choose from under
196
- `marimo.ui`.
197
- """
 
 
 
 
 
 
 
 
198
  )
199
- return
200
 
201
 
202
  @app.cell
203
- def __(mo):
204
- mo.md("""**🌊 Some UI elements.** Try interacting with the below elements.""")
205
- return
206
 
 
 
207
 
208
- @app.cell
209
- def __(mo):
210
- icon = mo.ui.dropdown(["πŸƒ", "🌊", "✨"], value="πŸƒ")
211
- return (icon,)
212
 
 
 
213
 
214
- @app.cell
215
- def __(icon, mo):
216
- repetitions = mo.ui.slider(1, 16, label=f"number of {icon.value}: ")
217
- return (repetitions,)
218
 
 
 
219
 
220
- @app.cell
221
- def __(icon, repetitions):
222
- icon, repetitions
223
- return
 
 
 
 
 
 
 
 
 
 
224
 
225
 
226
  @app.cell
227
- def __(icon, mo, repetitions):
228
- mo.md("# " + icon.value * repetitions.value)
229
- return
230
 
231
 
232
- @app.cell(hide_code=True)
233
- def __(mo):
234
- mo.md(
235
- """
236
- ## 3. marimo is just Python
 
 
 
 
237
 
238
- marimo cells parse Python (and only Python), and marimo notebooks are
239
- stored as pure Python files β€” outputs are _not_ included. There's no
240
- magical syntax.
241
 
242
- The Python files generated by marimo are:
243
 
244
- - easily versioned with git, yielding minimal diffs
245
- - legible for both humans and machines
246
- - formattable using your tool of choice,
247
- - usable as Python scripts, with UI elements taking their default
248
- values, and
249
- - importable by other modules (more on that in the future).
250
- """
 
 
 
 
 
 
 
 
 
 
 
 
251
  )
252
- return
253
 
254
 
255
- @app.cell(hide_code=True)
256
- def __(mo):
257
- mo.md(
258
- """
259
- ## 4. Running notebooks as apps
 
 
 
 
 
 
 
 
 
 
260
 
261
- marimo notebooks can double as apps. Click the app window icon in the
262
- bottom-right to see this notebook in "app view."
263
 
264
- Serve a notebook as an app with `marimo run` at the command-line.
265
- Of course, you can use marimo just to level-up your
266
- notebooking, without ever making apps.
267
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  )
269
- return
270
-
271
-
272
- @app.cell(hide_code=True)
273
- def __(mo):
274
- mo.md(
275
- """
276
- ## 5. The `marimo` command-line tool
277
-
278
- **Creating and editing notebooks.** Use
279
 
280
- ```
281
- marimo edit
282
- ```
283
 
284
- in a terminal to start the marimo notebook server. From here
285
- you can create a new notebook or edit existing ones.
 
286
 
 
287
 
288
- **Running as apps.** Use
 
 
 
 
 
 
 
 
 
289
 
290
- ```
291
- marimo run notebook.py
292
- ```
293
 
294
- to start a webserver that serves your notebook as an app in read-only mode,
295
- with code cells hidden.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
 
297
- **Convert a Jupyter notebook.** Convert a Jupyter notebook to a marimo
298
- notebook using `marimo convert`:
299
 
300
- ```
301
- marimo convert your_notebook.ipynb > your_app.py
302
- ```
303
 
304
- **Tutorials.** marimo comes packaged with tutorials:
 
 
 
305
 
306
- - `dataflow`: more on marimo's automatic execution
307
- - `ui`: how to use UI elements
308
- - `markdown`: how to write markdown, with interpolated values and
309
- LaTeX
310
- - `plots`: how plotting works in marimo
311
- - `sql`: how to use SQL
312
- - `layout`: layout elements in marimo
313
- - `fileformat`: how marimo's file format works
314
- - `markdown-format`: for using `.md` files in marimo
315
- - `for-jupyter-users`: if you are coming from Jupyter
316
 
317
- Start a tutorial with `marimo tutorial`; for example,
318
 
319
- ```
320
- marimo tutorial dataflow
321
- ```
322
 
323
- In addition to tutorials, we have examples in our
324
- [our GitHub repo](https://www.github.com/marimo-team/marimo/tree/main/examples).
325
- """
326
- )
327
- return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
 
330
- @app.cell(hide_code=True)
331
- def __(mo):
332
- mo.md(
333
- """
334
- ## 6. The marimo editor
 
 
 
 
 
 
 
 
 
335
 
336
- Here are some tips to help you get started with the marimo editor.
337
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  )
339
- return
340
 
341
 
342
  @app.cell
343
- def __(mo, tips):
344
- mo.accordion(tips)
345
- return
346
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347
 
348
- @app.cell(hide_code=True)
349
- def __(mo):
350
- mo.md("""## Finally, a fun fact""")
351
- return
352
 
 
353
 
354
- @app.cell(hide_code=True)
355
- def __(mo):
356
- mo.md(
357
- """
358
- The name "marimo" is a reference to a type of algae that, under
359
- the right conditions, clumps together to form a small sphere
360
- called a "marimo moss ball". Made of just strands of algae, these
361
- beloved assemblages are greater than the sum of their parts.
362
- """
363
  )
364
- return
365
-
366
-
367
- @app.cell(hide_code=True)
368
- def __():
369
- tips = {
370
- "Saving": (
371
- """
372
- **Saving**
373
-
374
- - _Name_ your app using the box at the top of the screen, or
375
- with `Ctrl/Cmd+s`. You can also create a named app at the
376
- command line, e.g., `marimo edit app_name.py`.
377
-
378
- - _Save_ by clicking the save icon on the bottom right, or by
379
- inputting `Ctrl/Cmd+s`. By default marimo is configured
380
- to autosave.
381
- """
382
- ),
383
- "Running": (
384
- """
385
- 1. _Run a cell_ by clicking the play ( β–· ) button on the top
386
- right of a cell, or by inputting `Ctrl/Cmd+Enter`.
387
-
388
- 2. _Run a stale cell_ by clicking the yellow run button on the
389
- right of the cell, or by inputting `Ctrl/Cmd+Enter`. A cell is
390
- stale when its code has been modified but not run.
391
-
392
- 3. _Run all stale cells_ by clicking the play ( β–· ) button on
393
- the bottom right of the screen, or input `Ctrl/Cmd+Shift+r`.
394
- """
395
- ),
396
- "Console Output": (
397
- """
398
- Console output (e.g., `print()` statements) is shown below a
399
- cell.
400
- """
401
- ),
402
- "Creating, Moving, and Deleting Cells": (
403
- """
404
- 1. _Create_ a new cell above or below a given one by clicking
405
- the plus button to the left of the cell, which appears on
406
- mouse hover.
407
-
408
- 2. _Move_ a cell up or down by dragging on the handle to the
409
- right of the cell, which appears on mouse hover.
410
-
411
- 3. _Delete_ a cell by clicking the trash bin icon. Bring it
412
- back by clicking the undo button on the bottom right of the
413
- screen, or with `Ctrl/Cmd+Shift+z`.
414
- """
415
- ),
416
- "Disabling Automatic Execution": (
417
- """
418
- Via the notebook settings (gear icon) or footer panel, you
419
- can disable automatic execution. This is helpful when
420
- working with expensive notebooks or notebooks that have
421
- side-effects like database transactions.
422
- """
423
- ),
424
- "Disabling Cells": (
425
- """
426
- You can disable a cell via the cell context menu.
427
- marimo will never run a disabled cell or any cells that depend on it.
428
- This can help prevent accidental execution of expensive computations
429
- when editing a notebook.
430
- """
431
- ),
432
- "Code Folding": (
433
- """
434
- You can collapse or fold the code in a cell by clicking the arrow
435
- icons in the line number column to the left, or by using keyboard
436
- shortcuts.
437
-
438
- Use the command palette (`Ctrl/Cmd+k`) or a keyboard shortcut to
439
- quickly fold or unfold all cells.
440
- """
441
- ),
442
- "Code Formatting": (
443
- """
444
- If you have [ruff](https://github.com/astral-sh/ruff) installed,
445
- you can format a cell with the keyboard shortcut `Ctrl/Cmd+b`.
446
- """
447
- ),
448
- "Command Palette": (
449
- """
450
- Use `Ctrl/Cmd+k` to open the command palette.
451
- """
452
- ),
453
- "Keyboard Shortcuts": (
454
- """
455
- Open the notebook menu (top-right) or input `Ctrl/Cmd+Shift+h` to
456
- view a list of all keyboard shortcuts.
457
- """
458
- ),
459
- "Configuration": (
460
- """
461
- Configure the editor by clicking the gears icon near the top-right
462
- of the screen.
463
- """
464
- ),
465
- }
466
- return (tips,)
467
 
468
 
469
  if __name__ == "__main__":
470
  app.run()
 
 
1
  import marimo
2
 
3
+ __generated_with = "0.12.0"
4
+ app = marimo.App(width="medium")
5
 
6
 
7
  @app.cell
8
+ def _():
9
  import marimo as mo
10
+ import pandas as pd
11
+ from svg import SVG, G, Circle, Path, Title, Rect, Line, Polygon, Text
12
+ import numpy as np
13
+ from collections import Counter
14
+ return (
15
+ Circle,
16
+ Counter,
17
+ G,
18
+ Line,
19
+ Path,
20
+ Polygon,
21
+ Rect,
22
+ SVG,
23
+ Text,
24
+ Title,
25
+ mo,
26
+ np,
27
+ pd,
28
+ )
29
 
30
 
31
  @app.cell
32
+ def _(pd):
33
+ #Data import
34
+
35
+ stage_data= pd.read_csv("C:/Users/paolo/Desktop/data visualisation project/stage_data.csv")
36
+ tdf_stages= pd.read_csv("C:/Users/paolo/Desktop/data visualisation project/tdf_stages.csv")
37
+ tdf_winners= pd.read_csv("C:/Users/paolo/Desktop/data visualisation project/tdf_winners.csv")
38
+ return stage_data, tdf_stages, tdf_winners
39
 
40
 
41
  @app.cell
42
+ def _(mo, pd, tdf_stages):
43
+ #Text blocks to insert the initial and final date used to filter the database
 
 
44
 
45
+ tdf_stages['Date'] = pd.to_datetime(tdf_stages['Date'], errors='coerce')
 
 
46
 
47
+ start_date_input = mo.ui.text(
48
+ label="Initial Date (YYYY-MM-DD)",
49
+ value=tdf_stages["Date"].min().strftime("%Y-%m-%d")
50
  )
51
+ end_date_input = mo.ui.text(
52
+ label="Final date (YYYY-MM-DD)",
53
+ value=tdf_stages["Date"].max().strftime("%Y-%m-%d")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  )
55
+ return end_date_input, start_date_input
 
 
 
 
 
 
 
 
 
 
 
 
56
 
 
 
 
 
 
57
 
58
+ @app.cell
59
+ def _(end_date_input, mo, start_date_input):
60
+ #show the text blocks in the output
 
 
 
61
 
62
+ mo.hstack(
63
+ [start_date_input, end_date_input], justify="start"
 
 
64
  )
65
  return
66
 
67
 
68
+ @app.cell
69
+ def _(mo):
70
+ #Slider to select the circles radius
71
+
72
+ radius =mo.ui.slider(start=1, stop=10, step=1, value=5, label="radius")
73
+ return (radius,)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
 
76
  @app.cell
77
+ def _(Counter, end_date_input, start_date_input, tdf_stages):
78
+ # Group the "type" variable in four groups
79
+ macro_class_mapping = {
80
+ 'Flat cobblestone stage': 'Plain',
81
+ 'Flat stage': 'Plain',
82
+ 'Flat Stage': 'Plain',
83
+ 'Half Stage': 'Other',
84
+ 'High mountain stage': 'Mountain',
85
+ 'Hilly stage': 'Hill',
86
+ 'Individual time trial': 'Chrono',
87
+ 'Intermediate stage': 'Other',
88
+ 'Medium mountain stage': 'Mountain',
89
+ 'Mountain stage': 'Mountain',
90
+ 'Mountain Stage': 'Mountain',
91
+ 'Mountain time trial': 'Chrono',
92
+ 'Plain stage': 'Plain',
93
+ 'Plain stage with cobblestones': 'Plain',
94
+ 'Stage with mountain': 'Mountain',
95
+ 'Stage with mountain(s)': 'Mountain',
96
+ 'Team time trial': 'Chrono',
97
+ 'Transition stage': 'Other'
98
+ }
99
 
100
+ tdf_stages['macro_class'] = tdf_stages['Type'].map(macro_class_mapping)
101
 
102
+ # Filter the database using the data inserted in the Text Blocks
103
+ start_date = start_date_input.value
104
+ end_date = end_date_input.value
 
 
 
 
 
 
 
105
 
106
 
107
+ filtered_df = tdf_stages[(tdf_stages['Date'] >= start_date) & (tdf_stages['Date'] <= end_date)]
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
+ # Find the 3 countries with most winning for each Type of stage
112
 
113
+ all_macro_classes = ['Plain', 'Hill', 'Mountain', 'Chrono']
 
 
 
 
114
 
115
+ macro_class_top3 = {}
116
+ for macro_class in all_macro_classes:
117
+ if macro_class in filtered_df['macro_class'].unique():
118
+ group = filtered_df[filtered_df['macro_class'] == macro_class]
119
+ top_countries = Counter(group['Winner_Country']).most_common(3)
120
+ macro_class_top3[macro_class] = [country for country, _ in top_countries]
121
+ while len(macro_class_top3[macro_class]) < 3:
122
+ macro_class_top3[macro_class].append("NA")
123
+ else:
124
+ macro_class_top3[macro_class] =[' ', ' ', ' ']
125
 
126
+ print(macro_class_top3)
127
+ return (
128
+ all_macro_classes,
129
+ end_date,
130
+ filtered_df,
131
+ group,
132
+ macro_class,
133
+ macro_class_mapping,
134
+ macro_class_top3,
135
+ start_date,
136
+ top_countries,
137
  )
 
138
 
139
 
140
  @app.cell
141
+ def _(tdf_winners):
142
+ ##Scale function for flat stages
 
143
 
144
+ X_MIN, X_MAX = tdf_winners["height"].min(), tdf_winners["height"].max()
145
+ Y_MIN, Y_MAX = tdf_winners["weight"].min(), tdf_winners["weight"].max()
146
 
 
 
 
 
147
 
148
+ SVG_X_MIN_P, SVG_X_MAX_P = 60, 150
149
+ SVG_Y_MIN_P, SVG_Y_MAX_P = 280, 470
150
 
 
 
 
 
151
 
152
+ def scale_x_plain(x):
153
+ return SVG_X_MIN_P + (x - X_MIN) / (X_MAX - X_MIN) * (SVG_X_MAX_P - SVG_X_MIN_P)
154
 
155
+ def scale_y_plain(y):
156
+ return SVG_Y_MAX_P - (y - Y_MIN) / (Y_MAX - Y_MIN) * (SVG_Y_MAX_P - SVG_Y_MIN_P)
157
+ return (
158
+ SVG_X_MAX_P,
159
+ SVG_X_MIN_P,
160
+ SVG_Y_MAX_P,
161
+ SVG_Y_MIN_P,
162
+ X_MAX,
163
+ X_MIN,
164
+ Y_MAX,
165
+ Y_MIN,
166
+ scale_x_plain,
167
+ scale_y_plain,
168
+ )
169
 
170
 
171
  @app.cell
172
+ def _(macro_class_top3, scale_x_plain, scale_y_plain, tdf_winners):
173
+ ## datapoints for plain stages
174
+ Cplain=str(macro_class_top3['Plain'][0])
175
 
176
 
177
+ datapoints_plain = []
178
+ for i in range(106):
179
+ if Cplain.capitalize() in tdf_winners["birth_country"][i] :
180
+ datapoints_plain.append(
181
+ {
182
+ 'x': scale_x_plain(tdf_winners["height"][i]),
183
+ 'y': scale_y_plain(tdf_winners["weight"][i]),
184
+ 'data-id': i
185
+ })
186
 
187
+ print(Cplain)
188
+ print(datapoints_plain)
189
+ return Cplain, datapoints_plain, i
190
 
 
191
 
192
+ @app.cell
193
+ def _(X_MAX, X_MIN, Y_MAX, Y_MIN):
194
+ ##Scale function for hilly stages
195
+
196
+ SVG_X_MIN_C, SVG_X_MAX_C = 210, 300
197
+ SVG_Y_MIN_C, SVG_Y_MAX_C = 280, 470
198
+
199
+ def scale_x_hill(x):
200
+ return SVG_X_MIN_C + (x - X_MIN) / (X_MAX - X_MIN) * (SVG_X_MAX_C - SVG_X_MIN_C)
201
+
202
+ def scale_y_hill(y):
203
+ return SVG_Y_MAX_C - (y - Y_MIN) / (Y_MAX - Y_MIN) * (SVG_Y_MAX_C - SVG_Y_MIN_C)
204
+ return (
205
+ SVG_X_MAX_C,
206
+ SVG_X_MIN_C,
207
+ SVG_Y_MAX_C,
208
+ SVG_Y_MIN_C,
209
+ scale_x_hill,
210
+ scale_y_hill,
211
  )
 
212
 
213
 
214
+ @app.cell
215
+ def _(i, macro_class_top3, scale_x_hill, scale_y_hill, tdf_winners):
216
+ ## datapoints for hilly stages
217
+ Chill=str(macro_class_top3['Hill'][0])
218
+
219
+ datapoints_hill = []
220
+ for j in range(106):
221
+ if Chill.capitalize() in tdf_winners["birth_country"][j]:
222
+ datapoints_hill.append(
223
+ {
224
+ 'x': scale_x_hill(tdf_winners["height"][j]),
225
+ 'y': scale_y_hill(tdf_winners["weight"][j]),
226
+ 'data-id': i
227
+ })
228
+ return Chill, datapoints_hill, j
229
 
 
 
230
 
231
+ @app.cell
232
+ def _(X_MAX, X_MIN, Y_MAX, Y_MIN):
233
+ ##Scale function for Mountain stages
234
+
235
+ SVG_X_MIN_M, SVG_X_MAX_M = 360, 450
236
+ SVG_Y_MIN_M, SVG_Y_MAX_M = 280, 470
237
+
238
+ def scale_x_Mountain(x):
239
+ return SVG_X_MIN_M + (x - X_MIN) / (X_MAX - X_MIN) * (SVG_X_MAX_M - SVG_X_MIN_M)
240
+
241
+ def scale_y_Mountain(y):
242
+ return SVG_Y_MAX_M - (y - Y_MIN) / (Y_MAX - Y_MIN) * (SVG_Y_MAX_M - SVG_Y_MIN_M)
243
+ return (
244
+ SVG_X_MAX_M,
245
+ SVG_X_MIN_M,
246
+ SVG_Y_MAX_M,
247
+ SVG_Y_MIN_M,
248
+ scale_x_Mountain,
249
+ scale_y_Mountain,
250
  )
 
 
 
 
 
 
 
 
 
 
251
 
 
 
 
252
 
253
+ @app.cell
254
+ def _(macro_class_top3, scale_x_Mountain, scale_y_Mountain, tdf_winners):
255
+ ## datapoints for Mountain stages
256
 
257
+ CMountain=str(macro_class_top3['Mountain'][0])
258
 
259
+ datapoints_Mountain = []
260
+ for k in range(106):
261
+ if CMountain.capitalize() in tdf_winners["birth_country"][k]:
262
+ datapoints_Mountain.append(
263
+ {
264
+ 'x': scale_x_Mountain(tdf_winners["height"][k]),
265
+ 'y': scale_y_Mountain(tdf_winners["weight"][k]),
266
+ 'data-id': k
267
+ })
268
+ return CMountain, datapoints_Mountain, k
269
 
 
 
 
270
 
271
+ @app.cell
272
+ def _(X_MAX, X_MIN, Y_MAX, Y_MIN):
273
+ ##Scale function for Chrono stages
274
+
275
+ SVG_X_MIN_CR, SVG_X_MAX_CR = 520, 600
276
+ SVG_Y_MIN_CR, SVG_Y_MAX_CR = 280, 470
277
+
278
+ def scale_x_Chrono(x):
279
+ return SVG_X_MIN_CR + (x - X_MIN) / (X_MAX - X_MIN) * (SVG_X_MAX_CR - SVG_X_MIN_CR)
280
+
281
+ def scale_y_Chrono(y):
282
+ return SVG_Y_MAX_CR - (y - Y_MIN) / (Y_MAX - Y_MIN) * (SVG_Y_MAX_CR - SVG_Y_MIN_CR)
283
+ return (
284
+ SVG_X_MAX_CR,
285
+ SVG_X_MIN_CR,
286
+ SVG_Y_MAX_CR,
287
+ SVG_Y_MIN_CR,
288
+ scale_x_Chrono,
289
+ scale_y_Chrono,
290
+ )
291
 
 
 
292
 
293
+ @app.cell
294
+ def _(macro_class_top3, scale_x_Chrono, scale_y_Chrono, tdf_winners):
295
+ #datapoints for Chrono stages
296
 
297
+ CChrono=str(macro_class_top3['Chrono'][0])
298
+ datapoints_Chrono = []
299
+ for z in range(106):
300
+ if CChrono.capitalize() in tdf_winners["birth_country"][z] :
301
 
302
+ datapoints_Chrono.append(
303
+ {
304
+ 'x': scale_x_Chrono(tdf_winners["height"][z]),
305
+ 'y': scale_y_Chrono(tdf_winners["weight"][z]),
306
+ 'data-id': z
307
+ })
 
 
 
 
308
 
309
+ return CChrono, datapoints_Chrono, z
310
 
 
 
 
311
 
312
+ @app.cell
313
+ def _(
314
+ Circle,
315
+ datapoints_Chrono,
316
+ datapoints_Mountain,
317
+ datapoints_hill,
318
+ datapoints_plain,
319
+ pd,
320
+ radius,
321
+ ):
322
+ #create circles for each stage type
323
+
324
+ circles_plain = []
325
+ for datapoint in datapoints_plain:
326
+ if not (pd.isna(datapoint["x"]) or pd.isna(datapoint["y"])):
327
+ circles_plain.append(
328
+ Circle(
329
+ cx=datapoint["x"],
330
+ cy=datapoint["y"],
331
+ r=radius.value,
332
+ fill="green",
333
+ fill_opacity=0.5,
334
+ stroke_width=1,
335
+ stroke="white"
336
+ )
337
+ )
338
 
339
+ circles_hill = []
340
+ for datapoint in datapoints_hill:
341
+ if not (pd.isna(datapoint["x"]) or pd.isna(datapoint["y"])):
342
+ circles_hill.append(
343
+ Circle(
344
+ cx=datapoint["x"],
345
+ cy=datapoint["y"],
346
+ r=radius.value,
347
+ fill="orange",
348
+ fill_opacity=0.5,
349
+ stroke_width=1,
350
+ stroke="white"
351
+ )
352
+ )
353
 
354
+ circles_mountain = []
355
+ for datapoint in datapoints_Mountain:
356
+ if not (pd.isna(datapoint["x"]) or pd.isna(datapoint["y"])):
357
+ circles_mountain.append(
358
+ Circle(
359
+ cx=datapoint["x"],
360
+ cy=datapoint["y"],
361
+ r=radius.value,
362
+ fill="brown",
363
+ fill_opacity=0.5,
364
+ stroke_width=1,
365
+ stroke="white"
366
+ )
367
+ )
368
 
369
+ circles_chrono= []
370
+ for datapoint in datapoints_Chrono:
371
+ if not (pd.isna(datapoint["x"]) or pd.isna(datapoint["y"])):
372
+ circles_chrono.append(
373
+ Circle(
374
+ cx=datapoint["x"],
375
+ cy=datapoint["y"],
376
+ r=radius.value,
377
+ fill="darkgray",
378
+ fill_opacity=0.5,
379
+ stroke_width=1,
380
+ stroke="white"
381
+ )
382
+ )
383
+ return (
384
+ circles_chrono,
385
+ circles_hill,
386
+ circles_mountain,
387
+ circles_plain,
388
+ datapoint,
389
  )
 
390
 
391
 
392
  @app.cell
393
+ def _(
394
+ CChrono,
395
+ CMountain,
396
+ Chill,
397
+ Cplain,
398
+ Line,
399
+ Polygon,
400
+ SVG,
401
+ Text,
402
+ circles_chrono,
403
+ circles_hill,
404
+ circles_mountain,
405
+ circles_plain,
406
+ macro_class_top3,
407
+ mo,
408
+ radius,
409
+ ):
410
+ #complete graph
411
+
412
+ plot = SVG(
413
+ width=700,
414
+ height=800,
415
+ elements=
416
+ [
417
+ # Rettangoli e poligoni
418
+ Polygon(points=[(30, 250), (180, 250), (180, 650), (30, 650)], fill="green", stroke="black"),
419
+ Polygon(points=[(30, 250), (70, 220), (220, 220), (180, 250)], fill="forestgreen", stroke="black"),
420
+ Polygon(points=[(180, 250), (330, 250), (330, 650), (180, 650)], fill="orange", stroke="black"),
421
+ Polygon(points=[(180, 250), (330, 250), (370, 220), (220, 220)], fill="chocolate", stroke="black"),
422
+ Polygon(points=[(180, 250), (330, 250), (330, 200)], fill="goldenrod", stroke="black"),
423
+ Polygon(points=[(180, 250), (220, 220), (370, 170), (330, 200)], fill="gold", stroke="black"),
424
+ Polygon(points=[(330, 250), (480, 250), (420, 130), (330, 200)], fill="maroon", stroke="black"),
425
+ Polygon(points=[(330, 650), (480, 650), (480, 250), (330, 250)], fill="chocolate", stroke="black"),
426
+ Polygon(points=[(330, 200), (370, 170), (450, 100), (520, 220), (480, 250), (420, 130)], fill="maroon", stroke="black"),
427
+ Polygon(points=[(480, 250), (630, 250), (670, 220), (520, 220)], fill="gray", stroke="black"),
428
+ Polygon(points=[(480, 250), (630, 250), (630, 650), (480, 650)], fill="gray", stroke="black"),
429
+ Polygon(points=[(630, 650), (670, 630), (670, 220), (630, 250)], fill="darkgray", stroke="black"),
430
+
431
+ # Linee
432
+ Line(x1=30, y1=500, x2=630, y2=500, stroke="black", stroke_width=1),
433
+ Line(x1=630, y1=500, x2=670, y2=480, stroke="black", stroke_width=1),
434
+
435
+ Line(x1=30, y1=570, x2=630, y2=570, stroke="black", stroke_width=1),
436
+ Line(x1=630, y1=570, x2=670, y2=550, stroke="black", stroke_width=1),
437
+
438
+ #scritte
439
+ Text(x=120, y=490, text="height", font_size=20, fill="darkgreen"),
440
+ Text(x=40, y=270, text="weight", font_size=20, fill="darkgreen"),
441
+ Text(x=270, y=490, text="height", font_size=20, fill="darkorange"),
442
+ Text(x=190, y=270, text="weight", font_size=20, fill="darkorange"),
443
+ Text(x=420, y=490, text="height", font_size=20, fill="brown"),
444
+ Text(x=340, y=270, text="weight", font_size=20, fill="brown"),
445
+ Text(x=570, y=490, text="height", font_size=20, fill="darkgray"),
446
+ Text(x=490, y=270, text="weight", font_size=20, fill="darkgray"),
447
+
448
+ Text(x=50, y=400, text=Cplain, font_size=60, fill="darkgreen"),
449
+ Text(x=200, y=400, text=Chill, font_size=60, fill="darkorange"),
450
+ Text(x=350, y=400, text=CMountain, font_size=60, fill="brown"),
451
+ Text(x=500, y=400, text=CChrono, font_size=60, fill="darkgray"),
452
+
453
+ Text(x=70, y=550, text=str(macro_class_top3['Plain'][1]), font_size=40, fill="darkgreen"),
454
+ Text(x=220, y=550, text=str(macro_class_top3['Hill'][1]), font_size=40, fill="darkorange"),
455
+ Text(x=370, y=550, text=str(macro_class_top3['Mountain'][1]), font_size=40, fill="brown"),
456
+ Text(x=520, y=550, text=str(macro_class_top3['Chrono'][1]), font_size=40, fill="darkgray"),
457
+
458
+ Text(x=85, y=620, text=str(macro_class_top3['Plain'][2]), font_size=20, fill="darkgreen"),
459
+ Text(x=235, y=620, text=str(macro_class_top3['Hill'][2]), font_size=20, fill="darkorange"),
460
+ Text(x=385, y=620, text=str(macro_class_top3['Mountain'][2]), font_size=20, fill="brown"),
461
+ Text(x=535, y=620, text=str(macro_class_top3['Chrono'][2]), font_size=20, fill="darkgray"),
462
+
463
+ ] + circles_plain + circles_hill + circles_mountain + circles_chrono,
464
+ )
465
 
 
 
 
 
466
 
467
+ mo.Html(plot.as_str())
468
 
469
+ mo.hstack(
470
+ [mo.Html(plot.as_str()), radius], justify="start"
 
 
 
 
 
 
 
471
  )
472
+ return (plot,)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
 
474
 
475
  if __name__ == "__main__":
476
  app.run()
477
+