Save current file to new location

Hey there !

I’m trying to save the current GH file in a specific location from button without opening a dialog box.
A specific filepath would be given, a specific file name (different from the current one).

I’ve somehow managed to find the way to save the file where it stands :slight_smile:
But I’m getting confused between GH_Document vs GH_DocumentIO …
On the “auto_save3” condition, it returns “file_name is not of a recognized type”… But it asks for GH_DocumentIO. Very confused I am.

(no need to say I’m quite new into python and new into python for Grasshopper)

Any help would be really appreciated ! :slight_smile:
Any good lecture on python for GH also !

Thanks !

import Grasshopper


active_gh = Grasshopper.Instances.ActiveCanvas.Document
IOactive = Grasshopper.Kernel.GH_DocumentIO(active_gh)

if auto_save2:
    #Save the file where it currently stands.
    Grasshopper.Kernel.GH_DocumentIO.Save(IOactive)

if auto_save3:
    #Should save the current file to another location
    Grasshopper.Kernel.GH_DocumentIO.SaveQuiet(IOactive,my_path)

I’m by no means an expert on this, but judging from the documentation, it seems like the GH_DocumentIO.SaveQuiet method only takes a single argument - a string path -, whereas in your example you’re passing in two parameters: IOactive and my_path.

The string path (i.e. text) should be an absolute filepath (e.g. “/Users/antoine/Documents/my_gh_doc.gh”), also referred to by full file path.

In Python, if you need to parse an absolute path from a filename (e.g. “my_gh_doc.gh”) and a directory path (e.g. “/Users/antoine/Documents”), you can simply use os.path.join(dir_path, filename). You need to import os for this to work.
The absolute path can then be passed to the GH_DocumentIO.SaveQuiet method.

Please note that IOactive from your code does not reference a string describing the document filename, but an instance of GH_DocumentIO.

In your case, you can get the name of the current Grasshopper document with active_gh.DisplayName.

May I ask if you use Python for your self-driving simulations or simply vanilla Grasshopper? By the way, great stuff!! Say hi to Oscar from me. :wink:

1 Like

Hey !

Thank you for the tips about the full file path ! It was actually the problem :slight_smile:
I also thought that GH_DocumentIO.SaveQuiet method only takes a single argument but it actually asks also for a GH_DocumentIO.

I find this C# documentation really difficult for python users… I hope python examples will continue to grow in that section !

So the final version is

import os
import Grasshopper

my_full_path = os.path.join(my_dir, my_file)
active_gh = Grasshopper.Instances.ActiveCanvas.Document
IOactive = Grasshopper.Kernel.GH_DocumentIO(active_gh)

if save_me:
Grasshopper.Kernel.GH_DocumentIO.SaveQuiet(IOactive, my_full_path)

Now I’ll check about saving current rhino in same location ! Should not be much different I guess :slight_smile:

Thank you very much !! :slight_smile:
I’m not using python in the decision making nor in the learning process. I’m relying on a Neural network component from Lunchbox . It’s not the best suited for this application, but it works well and is super easy to use !
I’ll probably switch to Owl which I think will provide faster decisions when the network is trained.
Besides that, the rest is vanilla Grasshopper (for 99% of all my videos) :slight_smile:
Oscar says hi also !! :racing_car:

You’re welcome! Hm, okay. Seems like the documentation is lacking some information here?

I fully agree! When you are a beginner, it can be difficult.
Much of it has to do more with understanding OOP (i.e. Object Oriented Programming), rather than C#, apart from data types (e.g. int, double, bool, string, etc.) - which you are never confronted by in Python -, since there are no type declarations.
Once I understood how classes work in Python, I managed to grasp a lot more how things are structure in the documentation/API. Classes are a big portion of OOP.

Very cool to see an application for these components! I always wanted to try ML in Grasshopper, but it’s rather cumbersome with Python, since most CPython libraries (i.e. NumPy, Pandas, etc.), which are prominently used in ML today, are not easily available in IronPython (that is included in Rhino). IronPython is a version of Python that is “compiled” from Microsoft’s .Net framework (i.e. C#) and the development has been sluggish for years.
CPython is faster and more advanced. It is compiled from C and C++.

You’re a savage! :smiley:
Are you “simply” animating sliders and exporting frames of the viewport? Do you use render mode or something else to get the nice visuals?

Seems like a cool dude this Oscar! :wink:

I have to step up my python game then !!

Hahaha, mmh thanks :smiley:

For all the videos i’ve made, the complete animation is happening on one slider that goes from 0 to 1. Even the ones with plenty of clips happening one after the other : only one slider controlling the clips and managing the animation one after the others :slight_smile:
So that if I want to redo (after a year) a certain animation, I don’t have to dive in the spaghetti mess, I just animate one slider. But it’s also because it’s a better challenge for me haha :smiley:

For the renders I use the Rendered Viewport with some custom materials. It’s a script from David Rutten that tweaks reflectivity and smoothness of the preview. I’ve seen Joseph Oster adding more option, but this is enough for me :slight_smile:


Python wise I’m actually trying to make the Cycles render work with the animate slider function. I’ve seen some good code bits from (if I remember correctly) you and Anders Deleuran.
I just need to sit and dig a bit into documentations… If I manage to do something with it, I’ll make a post to document it ! :slight_smile:

Nice, exactly like I imagined it! :smiley:

Very cool! Thanks for sharing the link.

Yes, that’s a great idea, however probably hard to do, since the slider animation would need to wait - for the viewport rendering to finish - , before capturing the image each frame. Maybe I’m wrong about this though? I’m no an expert on this.

Great, looking forward to it!

Yes I think too ! But look, you posted what I used for that ! :smiley:

The problem I had was refreshing the cylce rendered viewport just after the animated slider go up.
So basically I had the first image, then only background colour… But when fixing that, I’m sure there will be plenty of other problems :upside_down_face:
We will see !

Oh, ok, I see! :slight_smile: So you use it to delay the canvas from refreshing until the rendering is done.
I imagine the most difficult part here is to dial in the pause, since the rendering times could vary from frame to frame?

You could also look into exporting OBJ sequences, instead of using the slider animation. You would also export your animation frame by frame but as OBJ files instead of images.
OBJ sequences can be loaded into other CG apps (i.e. Maya, Cinema 4D, Blender. etc.) that are more capable animation tools than Rhino. This would allow you for instance to use their built-in renderer to export your animations, animate the viewport camera, introduce effects (e.g. motion blurring, bokeh, etc.).

Here’s a huge topic on this, if you’re interested:

More specifically here’s a working script from me, also from the above topic:

1 Like

That is correct, but I guess if the time step is high enough and the number of passes is limited, we should have same quality between all frames… but I’m absolutely not sure.

I’d like to stick with my beloved Rhino/Gh combo but damn that looks interesting !
Thank you very much, I’ll read all of that ! :slight_smile:
If I can’t make it work in rhino, I’ll definitely try those !

Feel free to PM me if you have any questions about the Python scripts.

1 Like