You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: notebooks/3_intro_functiontask_state.md
+50-49Lines changed: 50 additions & 49 deletions
Original file line number
Diff line number
Diff line change
@@ -4,9 +4,9 @@ jupytext:
4
4
extension: .md
5
5
format_name: myst
6
6
format_version: 0.13
7
-
jupytext_version: 1.14.0
7
+
jupytext_version: 1.15.0
8
8
kernelspec:
9
-
display_name: Python 3
9
+
display_name: Python 3 (ipykernel)
10
10
language: python
11
11
name: python3
12
12
---
@@ -17,7 +17,7 @@ Task might be run for a single set of input values or we can generate multiple s
17
17
18
18
Let's start from a simple `FunctionTask` that takes a list as an input:
19
19
20
-
```{code-cell}
20
+
```{code-cell} ipython3
21
21
---
22
22
jupyter:
23
23
outputs_hidden: false
@@ -31,7 +31,7 @@ import nest_asyncio
31
31
nest_asyncio.apply()
32
32
```
33
33
34
-
```{code-cell}
34
+
```{code-cell} ipython3
35
35
import pydra
36
36
37
37
@@ -45,52 +45,52 @@ task1 = add_two(x=[1, 2, 3])
45
45
46
46
Before we set any splitter, the task's `state` should be `None`
47
47
48
-
```{code-cell}
48
+
```{code-cell} ipython3
49
49
task1.state is None
50
50
```
51
51
52
-
Now, we can set the `splitter`by using the `split` method. Since our task has only one input, there is only one option to create a set of inputs, i.e. `splitter="x"`:
52
+
Now, we can set the `splitter` using the `split` method. Since our task has only one input, there is only one option to create a set of inputs, i.e. `split(splitter='x', x=[1, 2, 3])`; make sure you define the value of `x` in the splitter as you did in `task`:
53
53
54
-
```{code-cell}
55
-
task1.split('x')
54
+
```{code-cell} ipython3
55
+
task1.split('x', x=[1, 2, 3])
56
56
```
57
57
58
58
Now, we can check that our task has a `state`:
59
59
60
-
```{code-cell}
60
+
```{code-cell} ipython3
61
61
task1.state
62
62
```
63
63
64
64
And we can print information about the state:
65
65
66
-
```{code-cell}
66
+
```{code-cell} ipython3
67
67
print(task1.state)
68
68
```
69
69
70
70
within the `state` information about the splitter has been stored:
71
71
72
-
```{code-cell}
72
+
```{code-cell} ipython3
73
73
task1.state.splitter
74
74
```
75
75
76
76
Note, that *pydra* adds name of the function to the name of the input.
77
77
78
78
Now, we can run the task and check results:
79
79
80
-
```{code-cell}
80
+
```{code-cell} ipython3
81
81
task1()
82
82
task1.result()
83
83
```
84
84
85
85
We can also return results together with values of the input, we just have to set an additional argument `return_inputs` to `True` (or `val`)
86
86
87
-
```{code-cell}
87
+
```{code-cell} ipython3
88
88
task1.result(return_inputs=True)
89
89
```
90
90
91
91
If we want to return indices instead of values, we can set `return_inputs` to `ind`
92
92
93
-
```{code-cell}
93
+
```{code-cell} ipython3
94
94
task1.result(return_inputs='ind')
95
95
```
96
96
@@ -106,16 +106,16 @@ For tasks with a state *pydra* prepare all sets of inputs and run the task for e
106
106
107
107
We can also use `State` for functions with multiple inputs:
108
108
109
-
```{code-cell}
109
+
```{code-cell} ipython3
110
110
@pydra.mark.task
111
111
def add_var(a, b):
112
112
return a + b
113
113
```
114
114
115
115
Now we have more options to define `splitter`, it depends on the type of inputs and on our application. For example, we could have `a` that is a list, `b` that is a single value, and split over `a` values:
@@ -130,7 +130,7 @@ Now we have three results for each element from the `a` list and the value of `b
130
130
131
131
But we can have lists for both inputs, and use both inputs in the splitter. Let's assume that `a` and `b` are two elements lists.
132
132
133
-
```{code-cell}
133
+
```{code-cell} ipython3
134
134
task3 = add_var(a=[1, 2], b=[10, 100])
135
135
```
136
136
@@ -144,8 +144,8 @@ Now, we have two options to map the input values, we might want to run the task
144
144
145
145
Let's start from the scalar splitter, that uses parentheses in the syntax:
146
146
147
-
```{code-cell}
148
-
task3.split(('a', 'b'))
147
+
```{code-cell} ipython3
148
+
task3.split(('a', 'b'), a=[1, 2], b=[10, 100])
149
149
task3()
150
150
task3.result()
151
151
```
@@ -164,9 +164,9 @@ We can represent the execution by the graph:
164
164
165
165
For the outer splitter we will use brackets:
166
166
167
-
```{code-cell}
167
+
```{code-cell} ipython3
168
168
task4 = add_var(a=[1, 2], b=[10, 100])
169
-
task4.split(['a', 'b'])
169
+
task4.split(['a', 'b'], a=[1, 2], b=[10, 100])
170
170
task4()
171
171
task4.result()
172
172
```
@@ -181,17 +181,17 @@ Now, we have results for all of the combinations of values from `a` and `b`.
181
181
182
182
Note, that once you set the splitter, you will get error when you try to set the splitter again. However, you can always set `overwrite` to `True` if you really intend to change the splitter.
183
183
184
-
```{code-cell}
184
+
```{code-cell} ipython3
185
185
:tags: [raises-exception]
186
186
187
-
task4.split(('a', 'b'))
187
+
task4.split(('a', 'b'), a=[1, 2], b=[10, 100])
188
188
```
189
189
190
190
For more inputs we can create more complex splitter, and use scalar and outer splitters together. **Note, that the scalar splitter can only work for lists that have the same length, but the outer splitter doesn't have this limitation.**
191
191
192
192
Let's run one more example that takes four inputs, `x` and `y` components of two vectors, and calculates all possible sums of vectors. `x` components should be kept together with corresponding `y` components (i.e. scalar splitters: `("x1", "y1")` and `("x2", "y2")`), but we should use outer splitter for two vectors to get all combinations.
@@ -220,9 +221,9 @@ When we use `splitter`, we can also define `combiner`, if we want to combine tog
220
221
221
222
If we take the `task4` as an example and combine all results for each element of the input `b`, we can modify the task as follows:
222
223
223
-
```{code-cell}
224
+
```{code-cell} ipython3
224
225
task5 = add_var(a=[1, 2], b=[10, 100])
225
-
task5.split(['a', 'b'])
226
+
task5.split(['a', 'b'], a=[1, 2], b=[10, 100])
226
227
# adding combiner
227
228
task5.combine('b')
228
229
task5()
@@ -231,7 +232,7 @@ task5.result()
231
232
232
233
Now our result contains two elements, each one is a list. The first one contains results for `a=1` and both values of `b`, and the second contains results for `a=2` and both values of `b`. Let's print the result again using `return_inputs`:
233
234
234
-
```{code-cell}
235
+
```{code-cell} ipython3
235
236
all_results = task5.result(return_inputs=True)
236
237
print(f'first list, a=1: {all_results[0]}')
237
238
print(f'\n second list, a=2: {all_results[1]}')
@@ -243,9 +244,9 @@ print(f'\n second list, a=2: {all_results[1]}')
243
244
244
245
But we could also group all elements from the input `a` and have a different combined output:
245
246
246
-
```{code-cell}
247
+
```{code-cell} ipython3
247
248
task6 = add_var(a=[1, 2], b=[10, 100])
248
-
task6.split(['a', 'b'])
249
+
task6.split(['a', 'b'], a=[1, 2], b=[10, 100])
249
250
# changing the combiner
250
251
task6.combine('a')
251
252
task6()
@@ -254,7 +255,7 @@ task6.result()
254
255
255
256
We still have two elements in our results, but this time the first element contains results for `b=10` and both values of `a`, and the second contains results for `b=100` and both values of `a`.
256
257
257
-
```{code-cell}
258
+
```{code-cell} ipython3
258
259
all_results = task6.result(return_inputs=True)
259
260
print(f'first list, b=10: {all_results[0]}')
260
261
print(f'\n second list, b=100: {all_results[1]}')
@@ -266,9 +267,9 @@ print(f'\n second list, b=100: {all_results[1]}')
266
267
267
268
We can also combine all elements by providing a list of all inputs to the `combiner`:
268
269
269
-
```{code-cell}
270
+
```{code-cell} ipython3
270
271
task7 = add_var(a=[1, 2], b=[10, 100])
271
-
task7.split(['a', 'b'])
272
+
task7.split(['a', 'b'], a=[1, 2], b=[10, 100])
272
273
# combining all inputs
273
274
task7.combine(['a', 'b'])
274
275
task7()
@@ -287,7 +288,7 @@ This time the output contains one element that is a list of all outputs:
287
288
288
289
Note that list can be used as an input even without using any splitter, there are functions that take a list as a single input value:
289
290
290
-
```{code-cell}
291
+
```{code-cell} ipython3
291
292
@pydra.mark.task
292
293
def moment(lst, n):
293
294
return sum([i**n for i in lst]) / len(lst)
@@ -307,7 +308,7 @@ Let's say we want to calculate squares and cubes of integers from 2 to 5, and co
307
308
308
309
First we will define a function that returns powers:
309
310
310
-
```{code-cell}
311
+
```{code-cell} ipython3
311
312
:tags: [hide-cell]
312
313
313
314
@pydra.mark.task
@@ -317,17 +318,17 @@ def power(x, n):
317
318
318
319
Now we can create a task that takes two lists as its input, outer splitter for `x` and `n`, and combine all `x`:
The result should contain two list, the first one is for squares, the second for cubes.
329
330
330
-
```{code-cell}
331
+
```{code-cell} ipython3
331
332
:tags: [hide-cell]
332
333
333
334
squares_list = [el.output.out for el in task_ex1.result()[0]]
@@ -340,7 +341,7 @@ print(f'cubes: {cubes_list}')
340
341
341
342
We run task multiple times for multiple sets of input, but we didn't talk about the execution time. Let's create a function that sleeps for a second and run for four values:
The last option for running the task is to create a `Submitter` first and run the submitter (`Submitter` is also a callable object) with the task as a `runnable`:
All of the execution time should be similar, since all tasks are run by *pydra* in the same way, i.e. *pydra* creates a submitter with `ConcurrentFutures` worker, if a number of processors is not provided, `ConcurrentFutures` takes all available processors as `max_workers`. However, if we want to set a specific number of processors, we can set it using `n_procs` when creating a `Submitter`. Let's see how the execution time changes when we use `n_procs=2`.
0 commit comments