# Create, invoke and observe vtk custom event

**URL:** <https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794>\
**Category:** Development\
**Created:** [May 30, 2020, 2:09pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794 "2020-05-30T14:09:47Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![PaoloZaffino](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/paolozaffino/32/81052_2.png) [@PaoloZaffino](https://discourse.slicer.org/u/PaoloZaffino)\
**Post date:** [May 30, 2020, 2:09pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/1 "2020-05-30T14:09:48Z")

</div>

Hi all,  
I’m using the function SetParameter() of a vtkMRMLScriptedModuleNode object.  
From a different class I observe that node and I run a function if the parameter changes…all run smoothly right so far, since I have a single parameter to take care of.

What about if I need to set two parameters (not at the same time) and I want to get a different notification for each modified parameter?

Do I have to create, invoke and observe two different vtk custom events?

If so, do you have a python snippet of code to suggest?

Thank you!

Paolo

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [May 30, 2020, 4:54pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/2 "2020-05-30T16:54:26Z")

</div>

Hi Paolo -

Good point - right now you get the same ModifiedEvent no matter what parameter changed. You would need to keep track of the old values and check which one had changed.

Currently we just call `Modified` in `SetParameter`, but we could change that to be `this->InvokeEvent(vtkCommand::ModifiedEvent, name)`

> <https://github.com/Slicer/Slicer/blob/421d1c06a9ac4ead72bdd338dd7358ea48008b25/Libs/MRML/Core/vtkMRMLScriptedModuleNode.cxx#L144>

Then you should be able to get the parameter using the method described [here](https://discourse.slicer.org/t/custom-events-for-vtk/1286/3)

> [@Custom Events for VTK](https://discourse.slicer.org/t/custom-events-for-vtk/1286/3):
>
> For some types of data can add a decorator to your callback that interprets the call data in python. [https://github.com/Kitware/VTK/blob/master/Wrapping/Python/vtk/util/misc.py#L6-L27](https://github.com/Kitware/VTK/blob/master/Wrapping/Python/vtk/util/misc.py#L6-L27) For most data types in Slicer, a vtkObject is actually returned as a wrapped version of whatever concrete subclass was passed in the payload, so it actually covers all slicer events that come from nodes or the scene or other classes. You can also call InvokeEvent from python with a calldata (payload) argument. …

---

<div class="post-metadata">

**Author:** ![PaoloZaffino](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/paolozaffino/32/81052_2.png) [@PaoloZaffino](https://discourse.slicer.org/u/PaoloZaffino)\
**Post date:** [May 30, 2020, 8:53pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/3 "2020-05-30T20:53:43Z")

</div>

Hi Steve,  
thanks for helping.

Let me explain better my use case, maybe I do not need two events.  
We are working on arduino connection layer, the COVID19 situation slowed down the work, but we are confident to release something fully working soon.

I have my extension and I created a dedicated node. When a message is received from arduino I set it into the node and an event is fired as well. If one or more classes (e.g. something built on top of connection layer) are observing the node, they will be notified. I already did this and it works very well.  
In this case I need an event since I do not know when a message will be received.

At the same time I need also to send a message from Slicer to the board.  
The idea was to observe the node in the opposite direction and, in case, run the proper function into my logic extension. That’s why I asked for two events.  
Actually I do not need an event, because I know when I want to send a message.  
Which is the best way of exposing a function from my logic to someone that wants to send a message form his own piece of code?

Something “easy and raw” could be put in my logic something like:  
slicer.sendMessageToArduino = self.sendMessage()  
but I mean, it’s quite brutal!

Thanks a lot!  
Paolo

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [May 30, 2020, 10:03pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/4 "2020-05-30T22:03:41Z")

</div>

Hi Paolo - Ah, yes, I see what you mean.

Well, in this case maybe just do something like:

```auto
import Arduino
Arduino.ArduinoLogic(arduinoNode).sendMessage("ciao!")

```

---

<div class="post-metadata">

**Author:** ![PaoloZaffino](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/paolozaffino/32/81052_2.png) [@PaoloZaffino](https://discourse.slicer.org/u/PaoloZaffino)\
**Post date:** [May 30, 2020, 10:56pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/5 "2020-05-30T22:56:05Z")

</div>

Thanks @pieper!  
It is exactly what I was looking for!

---

<div class="post-metadata">

**Author:** ![PaoloZaffino](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/paolozaffino/32/81052_2.png) [@PaoloZaffino](https://discourse.slicer.org/u/PaoloZaffino)\
**Post date:** [May 30, 2020, 11:13pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/6 "2020-05-30T23:13:05Z")

</div>

Just a little edit: the node should be not given

This works:

> import Arduino  
> Arduino.ArduinoLogic().sendMessage(“ciao!”)

Thanks again!

---

<div class="post-metadata">

**Author:** ![PaoloZaffino](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/paolozaffino/32/81052_2.png) [@PaoloZaffino](https://discourse.slicer.org/u/PaoloZaffino)\
**Post date:** [June 1, 2020, 12:26pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/7 "2020-06-01T12:26:43Z")

</div>

Hi @pieper,  
actually I didn’t reach the point, sorry.

By using

> Arduino.ArduinoLogic().sendMessage(“ciao!”)

I have access to the generic function, but I actually need to access the method of an instance of the class.

When I run the module (by UI) I create an object of the logic class and then I establish a connection (with all the required parameters). I need to access the function of this specific object, not to the (static) method of the class.  
That’s why I thought the extremely raw was of putting into the logic constructor

> slicer.sendMessageToArduino = self.sendMessage()

Thanks for helping!

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [June 1, 2020, 3:29pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/8 "2020-06-01T15:29:48Z")

</div>

Hi Paulo -

Right - that’s what I was thinking in my original suggestion, to include an instance of your node in the constructor of the logic class. That way the node could provide the “context” so that the `sendMessage` could determine the right connection to use, perhaps by storing a connection ID as a parameter in the node.

Do you have your code available on line?

---

<div class="post-metadata">

**Author:** ![PaoloZaffino](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/paolozaffino/32/81052_2.png) [@PaoloZaffino](https://discourse.slicer.org/u/PaoloZaffino)\
**Post date:** [June 1, 2020, 3:34pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/9 "2020-06-01T15:34:21Z")

</div>

I’m afraid that a connection ID is not enough.  
Yes, the code is [here](https://github.com/pzaffino/SlicerArduinoController/blob/master/ArduinoConnect/ArduinoConnect.py)

Thanks a lot!

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [June 1, 2020, 4:14pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/10 "2020-06-01T16:14:39Z")

</div>

Are you planning to have multiple connections to different devices? If so, then your module can maintain a mapping from a connection ID, also stored in the node, and any other info you need, like file descriptor, state, or device config. Maybe make a helper class for all that and then in the logic you just have a dictionary that tracks them by ID.

By the way, did you try using [QSerialPort](https://doc.qt.io/qt-5/qserialport.html) instead of python serial? If you did you could replace all the polling with signal/slot event driven code that would be more efficient and also probably scale better.

---

<div class="post-metadata">

**Author:** ![PaoloZaffino](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/paolozaffino/32/81052_2.png) [@PaoloZaffino](https://discourse.slicer.org/u/PaoloZaffino)\
**Post date:** [June 1, 2020, 5:27pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/11 "2020-06-01T17:27:37Z")

</div>

Right now no, I’m not planning to support multiple devices (maybe in the future).  
Thanks for the qt solution…it’s incredible, qt has a solution for whatever problem!

Regarding the ID in the node, as far as I know, it is not enough for reading/writing, since I have to access the object.  
That’s why I thought to two events or to the raw top level exposure of the method during the object initialization.

Another raw solution could be to rely on a single event, store the action into the node parameter, and inspect the parameter to figure out which function has to be fired.  
Something like:

- “READ:50” if 50 has been read
- “WRITE:100” if I want to write 100

but, I mean, it’s a huge huge workaround!

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [June 1, 2020, 7:00pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/12 "2020-06-01T19:00:40Z")

</div>

Hmm, I’m not seeing where the issue is. It seems to me that if you have code that is build on top of the Arduino infrastructure you can have it access the methods of the Logic class as needed. Can you describe the use case scenario a bit more?

---

<div class="post-metadata">

**Author:** ![PaoloZaffino](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/paolozaffino/32/81052_2.png) [@PaoloZaffino](https://discourse.slicer.org/u/PaoloZaffino)\
**Post date:** [June 1, 2020, 7:41pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/13 "2020-06-01T19:41:32Z")

</div>

I have the logic where I run the arduino connection.  
When the data (a string) is received, I exposeit to the Slicer environment by putting it into a node parameter. In this way someone else interested in reading data (e.g. to built another module) can have access to the data just observing the node.

The problem is if the user (not me) wants to write a string from whatever point of slicer (again, for example, from his own module) to arduino. I have the function to send the data, but it’s “locked” into the instantiated logic object. I should expose this inner function of the instantiated logic object in order to be reachable from whatever point.  
That’s why I suggested (even if is not elegant) to punt into the constructor of the logic a line like:

> slicer.sendMessageToArduino = self.sendMessage

In this way the user ha just to run

> slicer.sendMessageToArduino(“test”)

to write the message.

Sorry for being not so linear!

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [June 1, 2020, 8:51pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/14 "2020-06-01T20:51:48Z")

</div>

Module logics are available from other modules. In scripted modules, typically the logic is instantiated by the widget (we did not want to make the module manager to instantiate it, as it would have made module reload more complicated). This is how is done in current scripted module template. You can access it by something like this: `slicer.modules.mymodule.widgetRepresentation.self().logic`. See some more information in the [PerkLab Slicer programming tutorials](https://www.slicer.org/wiki/Documentation/Nightly/Training#PerkLab.27s_Slicer_bootcamp_training_materials).

---

<div class="post-metadata">

**Author:** ![PaoloZaffino](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/paolozaffino/32/81052_2.png) [@PaoloZaffino](https://discourse.slicer.org/u/PaoloZaffino)\
**Post date:** [June 1, 2020, 9:23pm UTC](https://discourse.slicer.org/t/create-invoke-and-observe-vtk-custom-event/11794/15 "2020-06-01T21:23:34Z")

</div>

Thanks!  
That’s what I was looking for!
