# How to trigger LMB click events to activate a specific View node and update contents of 'Viewer Node' image data block using Python?

I am using two Viewer nodes to directly access pixel values of the rendering through bpy.data.images['Viewer Node'].pixels.I want to access the outputs of both of these nodes by activating them one by one using Python. However, it seems that I cannot activate them via Python. If I click on either of them the Viewer Node data block is immediately updated as the sum of the pixel values shows. For instance, clicking on Viewer2:

And doing np.array(bpy.data.images['Viewer Node'].pixels[:]).sum() will give me 292007.42460217333

Clicking on Viewer1 and doing np.array(bpy.data.images['Viewer Node'].pixels[:]).sum() will result in a different number. Doing the followings will not activate either of the Viewer nodes and I will always get the same number in the np.sum():

v1 = bpy.context.scene.node_tree.nodes['Viewer']
v2 = bpy.context.scene.node_tree.nodes['Viewer.001']

v1.select = True
v2.select = False

np.array(bpy.data.images['Viewer Node'].pixels[:]).sum()
292007.42460217333

v1.select = False
v2.select = True

np.array(bpy.data.images['Viewer Node'].pixels[:]).sum()
292007.42460217333


I also tried bpy.context.scene.node_tree.nodes.active = v1 after v1.select = True and v2.select = False lines but it still does not work.

None of these activate either of the Viewer nodes. It seems that I am doing the same thing as shown in the solutions provided here but I cannot activate the nodes, or update the image block without re-rendering. Another solution that I found is this one. However, it seems that Blender's Python API has changed a little bit for the newer versions of Blender (I am using 2.79) and I cannot use the method provided.

A promising solution seems to be coming from invoking clicking events as shown here but I don't know how I can do it for selecting nodes. So I wonder, does any one know how to activate the Viewer nodes via Python, possibly via invoking LBM events?

• The link you posted is not invoking clicking events at all, its capturing them. – batFINGER Mar 10 '18 at 22:28
• @batFINGER Sorry I couldn't clearly understand what the problem is there. I thought capturing the invocation means something a different, and relevant to my problem. So actually maybe the most relevant thing would be this – Amir Mar 10 '18 at 22:33
• Sorry, Also the answer in your last link is not relevant as it describes what very simplified logic is behind selecting an object in 3D view. Where the mouse is simulated with another 3D object. Not simulating events at all – J. Bakker Mar 11 '18 at 8:37
• @J.Bakker Well I thought this is the closest thing, not totally relevant. The point is to simulate the mouse in Blender through scripting. – Amir Mar 11 '18 at 9:16
• I don't see a way to make this work. I expect you will have to render to image. You can mount a tmpfs to keep these renders in ram and eliminate disk IO. To limit the number of files, render one, then read into numpy and append collected info to a data file and delete the render. – sambler Mar 11 '18 at 17:35

Very good question. But The answer at this moment is you can’t. The python interpreter needs to be finished in order to start the compositor recalculation. This is a background job and after it is finished you know for certain that the new image has been updated.

If we would have a possibility in the API to find out if the background job of the compositor is running we would be able to start a python thread or modal window to wait for this to happen and then continue the task you want to do.

Perhaps best solution ATM is to use the file output node to always store those all outputs and when needed read them back.

• The reason that I do not want to store files is that I am going to get millions of renderings and I cannot store them on disk. The disk will have enough space but will not be able to handle a couple of millions of meta-data files. So I need to store the images in Numpy arrays and store them in chunks on disk. I would really appreciate if you can look more into this problem and offer a solution. – Amir Mar 10 '18 at 9:36
• I updated the question. I think there is a way to do this actually. Let let me know if you can come up with some ideas on how I can invoke clicking events – Amir Mar 10 '18 at 19:38

I think you'll be a lot better off using a single Viewer node, and then toggling the viewer input with a Switch node:

You can toggle the node with this script:

import bpy
switch = bpy.context.scene.node_tree.nodes['Switch']
switch.check = True

• Thank you but I'm afraid your solution potentially adds another layer of complexity to the problem :( The thing is I am going to do millions of renderings. If I use one Viewer node I need to do two renderings to update the image buffer. Do you have any ideas on how I can probably simulate clicking on the nodes? – Amir Mar 10 '18 at 21:39