# More Pythonic VTK wrapping

**URL:** https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092
**Category:** Development
**Created:** [January 17, 2024, 10:23pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092 "2024-01-17T22:23:14Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![dyollb](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dyollb/32/7649_2.png) [@dyollb](https://discourse.vtk.org/u/dyollb)
#### Post date: [January 23, 2024, 5:57pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/21 "2024-01-23T17:57:30Z")

</div>

Nice 👍

What about type hints? The ITK pythonic api is generated dynamically and IDEs (vscode) have difficulty doing auto completion. This makes it nice to read but hard to write.

Do you see the properties/named arguments to the constructor in the help/dir? I mean if you print dir(some\_algorithm) or help(some\_algorithm).

---

<div class="post-metadata">

### Author: ![berk.geveci](https://discourse.vtk.org/user_avatar/discourse.vtk.org/berk.geveci/32/3146_2.png) [@berk.geveci](https://discourse.vtk.org/u/berk.geveci)
#### Post date: [January 23, 2024, 6:02pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/22 "2024-01-23T18:02:15Z")

</div>

Yup 🙂

---

<div class="post-metadata">

### Author: ![jaswantp](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jaswantp/32/10046_2.png) [@jaswantp](https://discourse.vtk.org/u/jaswantp)
#### Post date: [January 23, 2024, 6:08pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/23 "2024-01-23T18:08:26Z")

</div>

> [@dyollb](#):
>
> What about type hints? The ITK pythonic api is generated dynamically and IDEs (vscode) have difficulty doing auto completion. This makes it nice to read but hard to write.

Yes. VTK has a script to auto-generate interface files that help IDEs and language servers with type hints. The .pyi files are packaged in the python wheels, so you should already have them. The type hints are auto generated for the new property names too!

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [January 23, 2024, 10:59pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/24 "2024-01-23T22:59:21Z")

</div>

> [@berk.geveci](#):
>
> ```auto
> const std::vector<double> GetContours();
> void SetContours(const std::vector<double>& ctrs);
> 
> ```

Exposing C++ STL classes to the API seems like a bad idea to me. These changes will affect the Java wrappers as well.

---

<div class="post-metadata">

### Author: ![amaclean](https://discourse.vtk.org/user_avatar/discourse.vtk.org/amaclean/32/224_2.png) [@amaclean](https://discourse.vtk.org/u/amaclean)
#### Post date: [January 23, 2024, 11:38pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/25 "2024-01-23T23:38:13Z")

</div>

> [@berk.geveci](#):
>
> How about we call it PythonicAPI.

Done, I like it! It also looks much better and makes more sense, see here: [PythonicAPI](https://ajpmaclean.github.io/web-test/site/PythonicAPI/) on my test site. I’ll do a MR anyway, see [MR 322](https://gitlab.kitware.com/vtk/vtk-examples/-/merge_requests/322). This means everything should be in place for upgrading/creating examples when it happens.

@ben.boeckel I was uneasy about using Python1 - it had occurred to me that one day there may be a Python 4!

Thanks for the input!

---

<div class="post-metadata">

### Author: ![berk.geveci](https://discourse.vtk.org/user_avatar/discourse.vtk.org/berk.geveci/32/3146_2.png) [@berk.geveci](https://discourse.vtk.org/u/berk.geveci)
#### Post date: [January 24, 2024, 4:30pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/26 "2024-01-24T16:30:13Z")

</div>

Good point. Although I humbly disagree 🙂 I will start another thread to discuss this.

---

<div class="post-metadata">

### Author: ![ahernsean](https://discourse.vtk.org/user_avatar/discourse.vtk.org/ahernsean/32/5874_2.png) [@ahernsean](https://discourse.vtk.org/u/ahernsean)
#### Post date: [January 24, 2024, 10:00pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/27 "2024-01-24T22:00:42Z")

</div>

It’s too bad that you can’t do `source.filtera().filter()`, as that feels the most natural and similar to other “chaining” Python APIs.

While I love the idea of a function that calls `.Update()` and then returns the output (`.GetOutput()`), the word “execute” doesn’t convey that concept to me. It sounds like the filter is being run, but there’s no connotation of anything being returned by an “execute” method. What about `.generate()`? Or maybe `.get_result()`?

---

<div class="post-metadata">

### Author: ![berk.geveci](https://discourse.vtk.org/user_avatar/discourse.vtk.org/berk.geveci/32/3146_2.png) [@berk.geveci](https://discourse.vtk.org/u/berk.geveci)
#### Post date: [January 24, 2024, 10:10pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/28 "2024-01-24T22:10:51Z")

</div>

> It’s too bad that you can’t do `source.filtera().filter()` , as that feels the most natural and similar to other “chaining” Python APIs.

Not feasible with \> 1000 algorithms 🙂 Also, chaining is not as old as people might think. numpy doesn’t let you chain ufuncs for example (while PyTorch lets you chain functions).

> While I love the idea of a function that calls `.Update()` and then returns the output (`.GetOutput()` ), the word “execute” doesn’t convey that concept to me. It sounds like the filter is being run, but there’s no connotation of anything being returned by an “execute” method. What about `.generate()` ? Or maybe `.get_result()` ?

I hear you. I like `generate()`. Another option would be to use the ` __call__ ()` method. That would look like `vtkContourFilter(input=foo, contour=[10, 20])()`. We could also go a more functional route, like:

```auto
result = apply(vtkContour(contours=[10, 20]) >> vtkShrink(), input_data)

```

For full pipelines, this could look like

```auto
result = apply(vtkSomeReader(file_name="...") >> vtkContour(contours=[10, 20]) >> vtkShrink())

```

---

<div class="post-metadata">

### Author: ![jaswantp](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jaswantp/32/10046_2.png) [@jaswantp](https://discourse.vtk.org/u/jaswantp)
#### Post date: [January 25, 2024, 11:38pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/29 "2024-01-25T23:38:45Z")

</div>

The rshift operator overload, when combined with initializing properties through constructor allows for very readable code!

If you had to reproduce `testCaseManyAlgorithmsWithUserInput` in [TestAlgorithmNumberProtocol](https://gitlab.kitware.com/jaswant.panchumarti/vtk/-/blob/python-property-wrapping/Wrapping/Python/Testing/Python/TestAlgorithmNumberProtocol.py) in VTK python right now, one’d have to write a function, instantiate every one of those filters, name the instances and setup connections. In the new code, it’s much more readable and easier to code and customize.

Just for the sake of a visual comparison, here they are:

**Future**  
Lines of code: 12

```python
# A pipeline object can be reused with different input data objects.
pipeline = (
vtkElevationFilter()
  >> vtkShrinkFilter()
  >> vtkGeometryFilter()
  >> vtkPolyDataConnectivityFilter(color_regions=True, extraction_mode=VTK_EXTRACT_ALL_REGIONS)
  >> vtkPolyDataNormals()
)
cone = vtkConeSource(radius=5, resolution=8, height=2).execute()
print(pipeline.execute(cone))
cylinder = vtkCylinderSource(radius=6, resolution=9, height=3).execute()
print(pipeline.execute(cylinder))

```

**Now**  
Lines of code: 29

```python
def execute(input):
    elevator = vtkElelvationFilter()
    shrinker = vtkShrinkFilter()
    ugToPolyData = vtkGeometryFilter()
    connectivity = vtkPolyDataConnectivityFilter()
    connectivity.SetColorRegions(True)
    connectivity.SetExtractionMode(VTK_EXTRACT_ALL_REGIONS)
    normals = vtkPolyDataNormals()
    # build pipeline
    elevator.SetInputDataObject(input)
    shrinker.SetInputConnection(0, elevator.GetOutputPort(0))
    ugToPolyData.SetInputConnection(0, shrinker.GetOutputPort(0))
    connectivity.SetInputConnection(0, ugToPolyData.GetOutputPort(0))
    normals.SetInputConnection(0, connectivity.GetOutputPort(0))
    # run
    normals.Update()
    return normals.GetOutput()
# create a cone
cone = vtkConeSource()
cone.SetRadius(5)
cone.SetResolution(8)
cone.SetHeight(2)
print(execute(cone))
# create a cylinder
cylinder = vtkCylinderSource()
cylinder.SetRadius(6)
cylinder.SetResolution(9)
cylinder.SetHeight(3)
print(execute(cylinder))

```

Another benefit is that vtkAlgorithm(s) are constructed only the first time when the pipeline object is defined. Compare this with the below code snippet, where they are recreated. Of course, you could write a class and store references to the algorithms, but that’s just more complicated and annoying to do in the interpreter.

---

<div class="post-metadata">

### Author: ![jaswantp](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jaswantp/32/10046_2.png) [@jaswantp](https://discourse.vtk.org/u/jaswantp)
#### Post date: [January 25, 2024, 11:45pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/30 "2024-01-25T23:45:35Z")

</div>

It should also be way easier to mix and match different pipelines. I expect it would be less exhausting to prototype and develop custom modeling applications on top of VTK.

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [January 25, 2024, 11:53pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/31 "2024-01-25T23:53:12Z")

</div>

> [@jaswantp](#):
>
> ```auto
> # A pipeline object can be reused with different input data objects.
> pipeline = (
> vtkElevationFilter()
> >> vtkShrinkFilter()
> >> vtkGeometryFilter()
> >> vtkPolyDataConnectivityFilter(color_regions=True, extraction_mode=VTK_EXTRACT_ALL_REGIONS)
> >> vtkPolyDataNormals()
> )
> 
> ```

I would have thought this reads better with a left shift operator

```auto
pipeline = (vtkPolyDataNormals() << 
vtkPolyDataConnectivityFilter(color_regions=True, extraction_mode=VTK_EXTRACT_ALL_REGIONS) << 
vtkGeometryFilter() << 
vtkShrinkFilter() << 
vtkElevationFilter()
)

```

---

<div class="post-metadata">

### Author: ![jaswantp](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jaswantp/32/10046_2.png) [@jaswantp](https://discourse.vtk.org/u/jaswantp)
#### Post date: [January 25, 2024, 11:55pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/32 "2024-01-25T23:55:59Z")

</div>

Doesn’t that need to be read from right-to-left? I see your point of view because it’s easier to associate pipeline with the last filter in the chain i.e, normals filter.

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [January 26, 2024, 12:01am UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/33 "2024-01-26T00:01:01Z")

</div>

You can still read left to right.  
I read the `vtkPolyDataNormals` filter input depends on `vtkPolyDataConnectivityFilter` output. If I’m interested in where the poly data filter gets its input I read further to the right.

I’m not a Python expert but it seems more logical to me.

---

<div class="post-metadata">

### Author: ![amaclean](https://discourse.vtk.org/user_avatar/discourse.vtk.org/amaclean/32/224_2.png) [@amaclean](https://discourse.vtk.org/u/amaclean)
#### Post date: [January 26, 2024, 2:03am UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/34 "2024-01-26T02:03:51Z")

</div>

Wow!!! That is so impressive!

---

<div class="post-metadata">

### Author: ![amaclean](https://discourse.vtk.org/user_avatar/discourse.vtk.org/amaclean/32/224_2.png) [@amaclean](https://discourse.vtk.org/u/amaclean)
#### Post date: [January 26, 2024, 2:13am UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/35 "2024-01-26T02:13:51Z")

</div>

I prefer left to right: “\>\>” since we read left to right and pipes “|” in bash work left to right. For me: “a \>\> b” means do “a” first then feed the result into “b”, it also makes it easier to just add " \>\> c" at the end, if “c” is a new filter.

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [January 26, 2024, 2:21am UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/36 "2024-01-26T02:21:03Z")

</div>

You’re right. Pipes push data from left to right. I suppose I was thinking of the pipeline object more like a stream.

---

<div class="post-metadata">

### Author: ![berk.geveci](https://discourse.vtk.org/user_avatar/discourse.vtk.org/berk.geveci/32/3146_2.png) [@berk.geveci](https://discourse.vtk.org/u/berk.geveci)
#### Post date: [January 27, 2024, 6:00pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/37 "2024-01-27T18:00:31Z")

</div>

Hi folks,

We made some good progress with the wrapped properties and the pipeline connection with \>\>. See this gist for some examples:

> <https://gist.github.com/berkgeveci/49556d9ee14df32ab70c30837f7e54f1>

If there are any suggestions for an alternative to `execute()`, I am all ears. My preference is `execute` since I have bee using that term for \>20 years with VTK.

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [January 27, 2024, 11:48pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/38 "2024-01-27T23:48:40Z")

</div>

> [@berk.geveci](#):
>
> ```auto
> output_data = aReader.execute()
> # vs
> aReader.Update()
> output_data = aReader.GetOutput()
> 
> output_data = aFilter.execute(input_data)
> #vs
> aFilter.SetInputData(input_data)
> aFilter.Update()
> output_data = aFilter.GetOutput()
> 
> ```

To my mind `execute()` doesn’t return anything. Methods `build()` or `generate()` would be better.

Alternatively a breaking change to  
`aReader.GetOutput(bool update = false)`  
or  
`aFilter.GetOutput(vtkDataObject* data = nullptr)`

---

<div class="post-metadata">

### Author: ![Sebastien\_Jourdain](https://discourse.vtk.org/user_avatar/discourse.vtk.org/sebastien_jourdain/32/100_2.png) [@Sebastien\_Jourdain](https://discourse.vtk.org/u/Sebastien_Jourdain)
#### Post date: [January 27, 2024, 11:49pm UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/39 "2024-01-27T23:49:20Z")

</div>

I think I like it. Maybe providing an example with GlyphMapper and its input ports could be interesting.

---

<div class="post-metadata">

### Author: ![marcomusy](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marcomusy/32/95_2.png) [@marcomusy](https://discourse.vtk.org/u/marcomusy)
#### Post date: [January 28, 2024, 2:12am UTC](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092/40 "2024-01-28T02:12:08Z")

</div>

> [@berk.geveci](#):
>
> If there are any suggestions for an alternative to `execute()`, I am all ears. My preference is `execute` since I have bee using that term for \>20 years with VTK.

what about `get_output()`, or `run()`

[Previous page](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092.md?page=1)

[Next page](https://discourse.vtk.org/t/more-pythonic-vtk-wrapping/13092.md?page=3)
