Camera trace recording in Paraview - python

I use Paraview 5.8.1 but my question holds for older versions.
I want to generate a Python script to automate my visualizations. I use the "trace recorder" tool which records the actions I do in the GUI and translate them into
the Python script that would lead to the same result.
However this tool does not record everything : for instance camera position or orientation axes size modications are not translated whereas the Python functions to hold this do exist.
Is there any way to get the trace recorder to record everything ?

Simple answer: nope.
ParaView use a property mechanism. Lot of things are properties (filter parameters, color setting, ...) and are available for record. But camera are not. When the trace stops, an internal hook adds the last camera in the trace.
You can use this as a Macro to add the current Camera in the trace:
from paraview import simple
from paraview import smtrace
smtrace.Trace.get_accessor(simple.GetActiveView())
camera_trace = smtrace.SaveCameras.get_trace(None)
if camera_trace:
a = smtrace.Trace.Output.append_separated(
"#### saving camera placements for all active views")
a = smtrace.Trace.Output.append_separated(camera_trace)
That said, I'm not sure to see a use case ... If you want to see an animation of your scene, you cannot use the Trace mechanism but you should use the Animation View instead.

Related

How do programming languages draw GUI like Tkinter for example?

I'm a comp sci student studying some compiler design and I have a quick question that bugs me to no end.
I'm currently writing an Interpreter in JavaScript (run on nodeJS) that takes statements like:
x = 4
print x
Which would result in the console output:
4
I can parse these statements pretty easily and have them output stuff to the console window. But how would this process work with GUI applications?
The way I understand it is, let's take Python for example.
When you run python in the command line, it launches a console application which takes in python commands and interprets them. (I know it translates to bytecode first, but it does eventually get interpreted).
So like if it sees 1+1, I understand how it can parse this and return 2 to the console window that it is already running. Python in this case is itself is a console app, so it's intuitive that console output from user-inputted instructions can also be on the console.
I've been able to do THAT. But this ALSO works in python:
from tkinter import*
t = Tk()
How does THAT work? Does the Python Interpreter/VM somehow call a Win32 API function? Or does it draw its own window?
Thank you in advance, for any help given to clarify this.
tkinter is essentially just a Python interface to the Tk library. This is an open source library that runs on all popular operating systems and provides a consistent API for GUI elements.
I don't think Python has any built-in GUI functions, it relies on external libraries like this.
Somebody at some point long ago wrote a library that could directly access the screen and turn pixels on or off. Then, they wrote a function that takes two x,y pairs and computes all the pixels that need to be turned on to draw a line. The library would then call the function to turn pixels on or off.
Someone else then created a library that sits on top of that library, and uses it to not just draw lines, but draw boxes or circles and so on.
Someone else creates a library on top of that which can read font descriptions and turn that into text on the screen. And then someone creates a library that combines the font library and the line library to create a library that creates windows and checkbuttons. And then someone figures out how to add color, and object rotation, and 3d effects, and on and on.
Ultimate we end up with something like tkinter, which is a library that has functions for creating an input widget, which calls a tcl/tk library which converts the python to tcl, and which calls an X11 or DirectX or Win32 or Cocoa or OpenGL library which takes the input and calls some other function that ultimately turns a pixel on or off on the physical display.
When you deal with programming, A LOT of what you are able to do comes down to existing libraries and APIs. If you had to reinvent the wheel every time, you'd never get anything meaningful done.
A simpler example is your print() call. This is mearly a wrapper that writes to stdout. The bash shell / OS you're using handles what happens to stdout. GUIs are more or less the same thing, with just a slightly more complicated path.
tkinter is a python library for generating GUI interfaces. It itself, is nothing more than a wrapper for the more general, Tk library. Tk is a general purpose GUI library that works across platforms. It does this by creating utilizing code that's customized for each operating system's GUI library. It's the OS* itself that ends up creating the GUI.
*This is kind of a generalization as in some operating systems (such as those that utilize something such as Gnome) the GUI interface is more decoupled from the OS than one would often think.

GIMP Python or C Script, Access Canvas Constantly in Background

I'm having some trouble determining if I can run a background process which accesses the current canvas continuously. Basically I'd like to monitor the existing canvas and pipe that information to a network protocol (NDI or something similar) so that I can "live edit" an image. Frame rate isn't incredibly critical here but I would like to do something better than what I'm currently doing which is capturing the screen and streaming it.
I can't seem to find any documentation on running a plugin that doesn't perform an operation and then terminate. Ideally I'd like to start the plugin and just let it sit in the background reading at a set schedule.
Can anyone point me in the right direction? The API and documentation doesn't have a lot of examples and my initial plugins basically opens a window and then dies.
As a point of reference I use GIMP to edit masks for projection maps and I'm always on the lookout to avoid using Photoshop. I'd like to create an open-source tool for the NDI tools that already exist in Photoshop (or a Syphon/Spout option).

Embed widgets with jupyter-cadquery (threejs): wrong position on load

I am using jupyter-cadquery to visualize some 3D models made with CadQuery.
When visualizing the models on a Jupyter notebook, everything works as expected.
But when trying to embed the widget in an HTML document, it seems the camera, on load, is pointing to (0, 0, 0), not as expected. Once you interact with the widget, the camera will point to the expected coordinate.
Here is the code to reproduce the error and an animation of the mentioned problem (see instructions bellow on how to reproduce it with Binder):
from cadquery import Workplane
from ipywidgets import embed
from jupyter_cadquery.cad_view import CadqueryView
from jupyter_cadquery.cadquery import Assembly
from jupyter_cadquery.cadquery import Part
# Create a simple assembly
box1 = Workplane('XY').box(10, 10, 10).translate((0, 0, 5))
a1 = Assembly([Part(box1)], "example 1")
# Generate HTML
a1.collect_shapes()
view = CadqueryView()
for shape in a1.collect_shapes():
view.add_shape(shape["name"], shape["shape"], shape["color"])
renderer = view.render()
embed.embed_minimal_html('export.html', views=renderer, title='Renderer')
renderer
Note how the view of the cube "jumps" suddenly on interaction.
Could it be an issue with ipywidgets? Since the view is okay when displayed in the notebook.
How could it be fixed?
How to reproduce
You can reproduce it with Binder, without needing to create a local environment (admitedly, installing CadQuery/jupyter-cadquery is not the easiest/fastest thing to do):
https://mybinder.org/v2/gh/bernhard-42/jupyter-cadquery/master?urlpath=lab&filepath=examples%2Fcadquery.ipynb
Just execute the code above in a new empty notebook. See how the renderer shows the 3D model without any issues on the notebook:
After execution, an export.html document will also appear in the file list on the left. Open it and make sure to click on the "Trust HTML" button on top of the viewer and hit refresh. If you interact with the view, you can reproduce the issue.
Note that, also, the perspective is lost (that is not an orthogonal view). Fixing that would be a plus! ^^
This can be reproduced without the need of jupyter-cadquery, so a new question has been opened instead:
Embed widgets with pythreejs: wrong perspective and camera look-at
It took a few days, didn't get cadquery working properly, but your second question on this topic without cadquery made it possible to look at the issue...
The jumping happens because orbit.update() for target does not occurs and the function update() is not available in python; only in c++ or c#, etc. From the docs:
When animating the camera rotation above, we used the camera’s
quaternion
. This is the most robust method for
animating free-form rotations. For example, the animation above was created by first moving the camera manually, and then reading out its position and quaternion properties at the wanted views...
The text can be found here on page 12. And also discussed here at github.
However, the jumping can be reproduced in IPython if you apply the following:
renderer = Renderer(scene=scene, camera=camera, controls=[orbit], position=target, width=view_width, height=view_height)
here position is added with target coordinates [0, 5, 0] but the update for this is only done when you mouse-click and adjust to position of the cube/camera. The jump is similar/equal to the jump as seen in the export.HTML.
Conclusion: the programmed camera position is seen as a jump after manual interference due to the absense of the .update() function of the OrbitControls python class and thus not a bug or mistake.

How can I manually interact with a custom Graph Editor in Maya (Using Python)

I've been practicing my python/mel coding and have been interested in creating a graph editor. I did a lot of research online and found this previous question (How can I keep an object selected in the outliner after physically deselecting it in the 3d view?) that helped me out a lot. However, I am having an issue were I cannot manually edit the curves that are generated. I'm unsure as to why this is happening and can't seem to find any clear documentation. (I've looked up the command references for mel/python in Maya but it doesn't seem to have detailed explanations).
To be more clear, my goal is to use my mouse to move the curve information based on keyframe data (Exactly like Maya's own graph editor). I am using the code solution from the previous example (edited to include my own selection connections and frame conventions).
So after some research I decided the easiest thing was to use Maya's own graph editor within my interface
# GRAPH ROW
# Section for the graph editor to allow the user to change attributes
paneLayout( configuration='single', parent=form, width=620, height=320 )
# queries Maya's graph editor and places it within my frame
graph = cmds.getPanel(scriptType='graphEditor')
cmds.scriptedPanel( graph[0], e=True, unParent=True)
cmds.scriptedPanel( graph[0], e=True, parent=frame1)

Change desktop wallpaper on certain monitor? [duplicate]

I'm using:
ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER,
0, "picturefile", 0)
To change the wallpaper.
But I'm wondering if there's any simple way to put different wallpapers on each screen.
This feature isn't standard in windows though, but there are external applications like ultramon that do this. Anyone know how that works?
The way I thought it might work if I join the two images together into one and then make that the wallpaper, but then I still need a way to span one image accross both screens.
Also, how could I grab some info about the monitor setup, the resolution of each screen and their placement? Like what you see in the gui display settings in windows, but in numbers.
After joining the images together into a big image, you have to set the wallpaper mode to tiled to make it so the image spans the desktop (otherwise it will restart on each monitor).
Couple of ways to do this:
a) Using IActiveDesktop (which does not require Active Desktop to be used, don't worry). This is nicest as on Win7 the new wallpaper will fade in.
You create an IActiveDesktop / CLSID_ActiveDesktop COM object and then call SetWallpaper, SetWallpaperOptions and finally ApplyChanges. (As I'm not a Python dev, I'm not sure exactly how you access the COM object, sorry.)
OR:
b) Via the registry. This isn't as nice, but works well enough.
Under HKEY_CURRENT_USER\Control Panel\Desktop set:
TileWallpaper to (REG_SZ) 1 (i.e. the string "1" not the number 1)
WallpaperStyle to (REG_SZ) 0 (i.e. the string "0" not the number 0)
Then call SystemParameterInfo(SPI_SETDESKTOPWALLPAPER...) as you do already.
.
By the way, the code I'm looking at, which uses IActiveDesktop and falls back on the registry if that fails, passes SPIF_UPDATEINIFILE | SPIF_SENDCHANGE as the last argument to SystemParameterInfo; you're currently passing 0 which could be wrong.
EnumDisplayMonitors is the Win32 API for getting details on the monitors, including their screen sizes and positions relative to each other.
That API returns its results via a callback function that you have to provide. (It calls it once for each monitor.) I am not a Python developer so I'm not sure how you can call such a function from Python.
A quick Google for "Python EnumWindows" (EnumWindows being a commonly-used API which returns results in the same way) finds people talking about that, and using a Lambda function for the callback, so it looks like it's possible but I'll leave it to someone who knows more about Python.
Note: Remember to cope with monitors that aren't right next to each other or aren't aligned with each other. Your compiled image may need to have blank areas to make things line up right on all the monitors. If you move one of the monitors around and do a PrtScn screenshot of the whole desktop you'll see what I mean in the result.

Categories