Disable or Catch VTK warnings in vtkOutputWindow when embedding Mayavi - python-2.7

I'd like to either disable the VTK warning window or, better yet, catch them to handle with my application's logging system. My application is using an embedded mayavi view, and I don't want error windows popping up that I have no control over. The following code demonstrates the warning window.
import numpy as np
from mayavi import mlab
x1 = np.array([1, 1, 2, 3])
y1 = np.array([1, 1, 4, 2])
z1 = np.array([1, 1, 5, 1])
mlab.plot3d(x1, y1, z1)
mlab.show()
Ok, I've done some research and discovered that vtk.vtkObject.GlobalWarningDisplayOff() will disable the window completely, which is nice. Better yet the followingcode will log the warnings to a file (found it here):
def redirect_vtk_messages ():
""" Can be used to redirect VTK related error messages to a
file."""
import tempfile
tempfile.template = 'vtk-err'
f = tempfile.mktemp('.log')
log = vtkpython.vtkFileOutputWindow()
log.SetFlush(1)
log.SetFileName(f)
log.SetInstance(log)
So while this is nice, I'm still unable to pipe the warnings directly into a logging handler. I'd rather not have to have a vtk_log file next to my regular log files. Also I might want to handle the warnings in my GUI somehow, or give the user options on how to handle them and constantly watching a log file for changes seems like a poor way to do that.
Any suggestions on a robust pythonic way to handle vtk warnings in an application which embeds mayavi/vtk?

I don't know whether this will work in the Mayavi environment, but this works for Python wrappings to VTK
# pipe vtk output errors to file
errOut = vtk.vtkFileOutputWindow()
errOut.SetFileName("VTK Error Out.txt")
vtkStdErrOut = vtk.vtkOutputWindow()
vtkStdErrOut.SetInstance(errOut)

I guess this partially answer your question, but you could implement an error observer in python as explained here http://public.kitware.com/pipermail/vtkusers/2012-June/074703.html and add it to the vtk class you are interested.
In c++ I find much simpler to redirect the output to stderr (this example is for windows):
vtkSmartPointer<vtkWin32OutputWindow> myOutputWindow = vtkSmartPointer<vtkWin32OutputWindow>::New();
myOutputWindow->SetSendToStdErr(true);
vtkOutputWindow::SetInstance(myOutputWindow);
In python I tried
ow = vtk.vtkOutputWindow()
ow.SendToStdErrOn()
it sends the error to console, but I still see the vtk window and it doesn't really seem catching the errors.
Another option could be to recompile vtk with VTK_USE_DISPLAY turned off ( http://osdir.com/ml/python-enthought-devel/2009-11/msg00164.html). I am not going to try this because I am using the vtk distribution already compiled in paraview

You can create a subclass deriving from vtkOutputWindow and implement your message handling in the method void DisplayText(const char* someText). I did this is in a C++ project to redirect all output to cerr and even suppress specific warnings.

An approach I found similar to #SciCompLover's answer that suppresses the output window while also printing to the console:
import vtk
vtk_out = vtk.vtkOutputWindow()
vtk_out.SetInstance(vtk_out)
Tested on Mayavi 4.7.1 with VTK 8.2.0 on Windows and MacOS.

Related

Better looking Tkinter File Dialogs for Python 2.7

In my application, the user needs to browse for files. However, the askdirectory from tkFileDialog isn't really comfortable for using and browsing files since it's somewhat outdated.
It looks like this:
What I want to achieve should look like the "default" windows browse dialog. Like this:
(Source https://www.pythontutorial.net/tkinter/tkinter-open-file-dialog/)
I am not sure (since I couldn't find proof) but I remember someone telling me that it looks like this because I am using Python 2.7 and not 3+.
Is that true? Does an alternative exist?
It seems it has something to do with your version, as I have done a bit of research and I am using python 3 with the included tkinter and it shows a normal windows explorer popup. So, if you are using one of the up-to-date versions, it should be the OS' default. (I am unable to test that as python 2 will not work properly on my machine although I can confirm since you are using an older one)
I recreated your case with this code:
from tkinter import *
root = Tk()
filedialog.askdirectory()
root.mainloop()
You can try using askopenfilename(). It displays the standard Open File dialog box.
For example:
from tkinter import *
from tkinter import filedialog as fd
root = Tk()
root.title("Button to open files")
root.geometry("500x500")
def openfd(*args):
askk = askopenfilename()
btn = Button(root, text="Click to open file", command=openfd)
btn.place(x=200, y=200)
root.mainloop()
You can read more about it at https://www.pythontutorial.net/tkinter/tkinter-open-file-dialog/.

Qt Creator not working with GDB Pretty Printing

I'm attempting to use Qt Creator to develop on Unreal Engine 4 in Linux. I've run into an issue with the debugger: I'm unable to get Qt Creator to use GDB's pretty printers.
Epic has written pretty printers for their custom containers (like their string class) and these work great in GDB. From Qt Creator's Debugger Log, I can see that GDB is registering these printers. In fact, I can even enter a "print " command and the output is formatted nicely. However, entering the variable as an expression in the watch window, all I see is the memory address the FString points at.
Specifically, here is the debugger command issued and the resulting output when I add the FString variable "Filename" to the watch window:
Command:
140python theDumper.fetchVariables({"autoderef":1,"context":"","displaystringlimit":"100","dyntype":1,"expanded":["local","watch","inspect","local.Filename.Data","local.Filename","return"],"fancy":1,"formats":{},"nativemixed":0,"partialvar":"watch.0","passexceptions":0,"qobjectnames":0,"resultvarname":"","stringcutoff":"10000","token":140,"typeformats":{},"watchers":[{"exp":"46696c656e616d65","iname":"watch.0"}]})
<Rebuild Watchmodel 16 # 09:05:19.576 [54836ms] >
Output:
dADJUSTING CHILD EXPECTATION FOR local.Filename
dADJUSTING CHILD EXPECTATION FOR local.Filename.Data
<140python theDumper.fetchVariables({"autoderef":1,"context":"","displaystringlimit":"100","dyntype":1,"expanded":["local","watch","inspect","local.Filename.Data","local.Filename","return"],"fancy":1,"formats":{},"nativemixed":0,"partialvar":"watch.0","passexceptions":0,"qobjectnames":0,"resultvarname":"","stringcutoff":"10000","token":140,"typeformats":{},"watchers":[{"exp":"46696c656e616d65","iname":"watch.0"}]})
>&"python theDumper.fetchVariables({\"autoderef\":1,\"context\":\"\",\"displaystringlimit\":\"100\",\"dyntype\":1,\"expanded\":[\"local\",\"watch\",\"inspect\",\"local.Filename.Data\",\"local.Filename\",\"return\"],\"fancy\":1,\"formats\":{},\"nativemixed\":0,\"partialvar\":\"watch.0\",\"passexceptions\":0,\"qobjectnames\":0,\"resultvarname\":\"\",\"stringcutoff\":\"10000\",\"token\":140,\"typeformats\":{},\"watchers\":[{\"exp\":\"46696c656e616d65\",\"iname\":\"watch.0\"}]})\n"
>~"data=[{iname=\"watch.0\",name=\"0\",numchild=\"0\",valueencoded=\"notaccessible\",value=\"\",},{iname=\"watch.0\",wname=\"46696c656e616d65\",numchild=\"1\",type=\"FString &\",value=\"\",address=\"0x7fffffff76b8\",},],typeinfo=[],partial=\"1\"\n"
>~"\"[{'d_d_ptr': 3, 'cannotBeQObject': 3}, [['locals', 117], ['watches', 837842], ['safePrint', 54]]]\"\n"
>140^done
<Rebuild Watchmodel 16 # 09:05:19.576 [54836ms] >
sFinished retrieving data
(Not sure if the "ADJUSTING CHILD EXPECTATION FOR" lines were for the previous command or this one)
Toggling the "Load system GDB pretty printers" option doesn't seem to have any effect.
Searching the web hasn't yielded much for me so far. Any help would be greatly appreciated!
Edit: oh this is interesting. I did a diff of the output with pretty printing disabled vs enabled. With it enabled, I get:
<23importPlainDumpers on
sStopped at breakpoint 1 (1) in thread 1.
<24-thread-info
>&"importPlainDumpers on\n"
>&"Python Exception <type 'exceptions.AttributeError'> 'function' object has no attribute 'subprinters': \n"
>&"Error occurred in Python command: 'function' object has no attribute 'subprinters'\n"
>23^error,msg="Error occurred in Python command: 'function' object has no attribute 'subprinters'"
Edit 2: Looking into it more, it appears Qt Creator may not support pretty printers that involve using lookup functions. Is this the case?
Okay. It appears Qt Creator expects pretty printers to conform to the structure defined by the PrettyPrinter and SubPrettyPrinter objects, and enforced by the register_pretty_printer() function, defined in gdb's printing.py script and documented here: https://sourceware.org/gdb/onlinedocs/gdb/gdb_002eprinting.html
Unreal's printers do not do this.
However, even if they did, it appears Qt Creator's import code will only import subprinters, not parent pretty printers (refer to importPlainDumpers() in gdbbridge.py). It seems the best way to solve this is to update Unreal's printers to follow the examples I can find of using a function to build 'RegexpCollectionPrettyPrinter's.

Matplotlib Qt4 GUI programming - replace plt.figure() with OO equivalent

I have an App made using Qt4 Designer which inserts a matplotlib figure into a container widget.
The code to generate the figure comes from another module, obspy:
self.st.plot(fig = self.rawDataPlot)
https://docs.obspy.org/packages/autogen/obspy.core.stream.Stream.plot.html
Normally, this would create and show a matplotlib figure for the st object's data, which is time-series. When the fig parameter is specified this tells self.st.plot to plot to an existing matplotlib figure instance.
The code I have to generate the figure and then position it in my GUI widget is:
def addmpl(self, fig, layout, window): # code to add mpl figure to Qt4 widget
self.canvas = FigureCanvas(fig)
layout.addWidget(self.canvas)
self.canvas.draw()
self.toolbar = NavigationToolbar(self.canvas,
window, coordinates=True)
layout.addWidget(self.toolbar)
self.rawDataPlot = plt.figure() # code to create a mpl figure instance
self.st.plot(fig = self.rawDataPlot) # plot time-series data to existing matplotlib figure instance
self.addmpl(self.rawDataPlot, self.mplvl, self.mplwindow) # add mpl figure to Qt4 widget
What I want to do is instantiate a matplot figure (for use by self.st.plot) but in a way which avoids using plt.figure(), as I have read that this is bad practice when using object-oriented programming.
If I replace plt.figure() with Figure() (from matplotlib.figure.Figure()) I get an error:
AttributeError: 'NoneType' object has no attribute 'draw'
As it stands, the App runs fine if I use plt.figure(), but is there a clean way to avoid using is and is it even necessary for my case?
PS, the code snippets here are taken from a larger source, but I think it gets the point across..
In principle both methods should work.
Whether you set self.rawDataPlot = plt.figure() or self.rawDataPlot = Figure() does not make a huge difference, assuming the imports are correct.
So the error is most probably triggered within the self.st.plot() function. (In general, if you report errors, append the traceback.)
Looking at the source of obspy.core.stream.Stream.plot there is a keyword argument
:param draw: If True, the figure canvas is explicitly re-drawn, which
ensures that existing figures are fresh. It makes no difference
for figures that are not yet visible.
Defaults to True.
That means that apparently the plot function tries to draw the canvas, which in the case of providing a Figure() hasn't yet been set.
A good guess would therfore be to call
self.rawDataPlot = Figure()
self.st.plot(fig = self.rawDataPlot, draw=False)
and see if the problem persists.

Issue with configure_traits when using Enthought Canopy

I was following the tutorial "Writing a graphical applications for scientific programming using TraitsUI
http://code.enthought.com/projects/traits/docs/html/tutorials/traits_ui_scientific_app.html
and tested the following code snippet:
from enthought.traits.api import *
from enthought.traits.ui.api import *
class Camera(HasTraits):
""" Camera object """
gain = Enum(1, 2, 3,
desc="the gain index of the camera",
label="gain", )
exposure = CInt(10,
desc="the exposure time, in ms",
label="Exposure", )
def capture(self):
""" Captures an image on the camera and returns it """
print "capturing an image at %i ms exposure, gain: %i" % (
self.exposure, self.gain )
if __name__ == "__main__":
camera = Camera()
camera.configure_traits()
camera.capture()
If I run this at the command line it works as advertised. A GUI pops up. You adjust the parameters, and when you click "OK" it returns the modified values. But when I run the same code from within the Canopy editor by clicking the run button the default parameters print immediately; then the window pops up. When you then adjust the parameters in the GUI and click "OK" the GUI exits but the new parameter values don't print.
It is as if somehow camera.capture() is running before camera.configure_traits.
First, I would suggest using this newer version of the tutorial: http://docs.enthought.com/traitsui/tutorials/traits_ui_scientific_app.html
The one you linked to references materials for TraitsUI version 3, whereas the one above is for the version you're likely using (version 4). The newer tutorial uses the newer module names, traitsui.api instead of enthought.traits.ui.api for example.
As to why Canopy displays the values immediately, this is the expected behavior when running the program:
if __name__ == "__main__":
camera = Camera()
camera.configure_traits()
camera.capture()
When run as __main__ (i.e., not imported as a module by another script), the script does these three things in order: creates an instance of Camera(), pops up the GUI (configure_traits), and then executes the capture method that prints the current values (which are "1" and "10" by default).
The OK/Cancel buttons are not hooked into setting these values. As a test, try changing the exposure or gain but instead of clicking the buttons, try inspecting these attributes from within Canopy's IPython prompt while the GUI is still open: camera.gain or camera.exposure should return the newly set values.

'PyCObject_Import("cairo", "CAPI")' C++ call yields segfault, 'import cairo' on python works

I am running OSX Lion and trying to import the python module for goocanvas, using python2.7.
I managed to successfully compile pygoocanvas-0.14.1, but when I try to import goocanvas through the python2.7 console, I get a segfault. After some debugging, I'm led to this code:
DL_EXPORT (void)
initgoocanvas (void)
{
PyObject *m, *d;
fprintf(stderr,"init<< \n");
// Pycairo_IMPORT; // XXX removed, it expands to the line below, anyways
Pycairo_CAPI = (Pycairo_CAPI_t*) PyCObject_Import("cairo", "CAPI"); // ADDED XXX
fprintf(stderr,"after import<< \n");
if (Pycairo_CAPI == NULL) {
return;
}
I discovered that the segfault happens when the C++ code of the goocanvas python module tries to import the "cairo" library through PyCObject_Import("cairo", "CAPI"). However, if I try to import the cairo module directly through the python2.7 console via import cairo, it works.
How should I proceed? I have a blind seg fault and no idea on why it happens. Remembering that I managed to compile the python goocanvas module, but it segfaults upon trying to import it on python.
What kind of console are you using? I think gtk/glib has some hooks to enable running the main loop concurrently with the REPL. This means that threads are in use, which may cause crashes if glib.threads_init() was not called.
IMHO this is broken by design, because by just importing glib or any g* module a sane Python program that uses any threads will suddenly start to segfault. Supporting threading should be the default.
In our case, the crash was caused by the logging system of glib which was forwarded to Python without holding the GIL.