MacOS : Matplotlib in C4D
-
Hello everyone,
So I have a very niche issue. We developed a Python plugin for C4D for our client.
One of the use case in this plugin is to be able to display graphs inside of C4D, in a window.
To do this, we used matplotlib. After some testing and issues, we managed to have everything working, with the graphs opening in an interactive mode, ...
FYI, the matplotlib backend we had to use is Qt5Agg, with PyQt5 installed.The only issue we have is on MacOS. When the graphs display, the app icon (on the dock) change to the matplotlib one, instead of C4D (not a big issue really).
The bigger issue is the navigation bar (on top of the screen, with Files, Edit, Window, ...) completely changes and the C4D menus disappear.
The only way to make it come back, once the graphs are closed, is to click the "new scene" button. That way C4D takes back the main thread and displays the menu again (the logo on the dock doesn't change though).So my questions are :
- has anybody ever had this issue
- is there a way we can "refresh" C4D to make it take back the hand on the main thread and refresh the navigation bar without having the user click anywhere
Thank you in advance !
-
Hey @GSenechal,
Thank you for reaching out to us. First I must quote from the Python Libraries Manual:
Maxon Computer cannot provide support for third party libraries written for CPython and their compatibility with the Python interpreters shipped with Cinema 4D. While our Python interpreters are derived from the respective CPython builds, they are not identical to them. Popular Python libraries as for example
numpy
might not work at all or only with a reduced feature set. The Cinema 4D Python interpreters are provided as-is and not meant to be fully CPython compliant.There are quite a few Python libraries that do not work properly with our CPython interpreter, usually because they run some executable and/or expect data to live in certain hard-coded places.
matplotlib
is one of the Python libraries that runs an executable (the output window) which is meant to switch place with the Python interpreter - which is then either the running Cinema 4D or c4dpy instance.Our APIs do not offer any (intentional) functionalities to force a running Cinema 4D instance to be set into focus. You could get creative here and track window handles with the respective OS libraries to ensure that Cinema 4D stays in focus. But that would be out of scope of support, and will likely also end up in a messy solution as you then must also make sure that the mechanism does not enforce focus when the user is trying to tab to Photoshop for example.
I do not really have a good solution for you. Most of the
matplotlib
alternatives also come with an executable or are just a wrapper (e.g.,seaborn
). You could try bokeh, it is quite nice too. It outputs to HTML and JS and is written in pure Python AFAIK (better double check). You could then display the output with an c4d.HtmlViewerCustomGui. Last but not least, it is of course a bit of an heresy to use a plotting library in Cinema 4D. It depends on the complexity of the plot type but for the simple ones, you should be able to produce nice plots with a few lines of code. To make your life easier, you could also store building blocks for plots as scene files or assets.You can of course also try to hack-fix this, but the warning in our docs exist for a reason, and over time you might run into other side effects. I would recommend a
bokeh
or pure Cinema 4D based solution when the time budget somehow allows that.PS: Maybe @m_adam, our Python developer, has here a deeper insight, but he will likely just say the same.
Cheers,
Ferdinand -
Hello Ferdinand,
Thank you for the very fast answer. I was expecting this kind of answer, as it's quite out of the initial scope of the SDK.
Unfortunately, we cannot really switch to anything other than matplotlib, as we already have a complete functioning workflow, with downsampling & all.. We need to keep it interactive.
My idea right now is to find a way to make C4D to take back the main thread, so i'll make a few tests (creating a new object in the scene, creating a new scene, ...) so the users don't have to do anything.
Have a nice day !
-
FYI : I managed to "fix" the issue with the navigation bar with a simple trick :
c4d.documents.SetActiveDocument(c4d.documents.GetActiveDocument())This makes C4D refresh in a way, taking the main thread back and re-adding its menu to the MacOS navigation bar
-
I am glad that you found your workaround. But I would try to avoid reattaching the active document when possible as this could have unforeseen side effects, this might for example impact simulations. I would first try less intrusive things like
c4d.gui.GeUpdateUI
or a simplec4d.EventAdd
.Cheers,
Ferdinand -
Hey @ferdinand ,
I already tried the c4d.gui.GeUpdateUI and c4d.EventAdd before with no luck, that's why i switched to setting the active document. Thank you for the warning though, i wasn't aware of this so i'll keep an eye for it !
Best regards
-
Hi I'm not a big expert of PyQt5, but I think you need to set the attribute Qt.AA_DontCreateNativeWidgetSiblings Attribute.
Cheers,
Maxime.