-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Example for experimental workflows #38
Comments
Hey @SteffenBrinckmann, Glad to hear you're working with it and thanks for the feedback!
💯 We currently depend directly on I don't have a timeframe right now, but it is correct criticism and there's a plan in place for resolving it.
The syntax is still evolving, but it's true that right now the However, you can accomplish this in one line by calling the node/workflow itself -- which starts by updating the input based on the arguments, and then runs it. For workflows the arguments have to be keyword, but for function nodes positional arguments are ok too. In your example I guess this would look like out = wf(step__name='sem', step__param={'voltage': 30}) For workflows and macros you can define
So I definitely agree there's lots of room for improving output beauty, but if I understand correctly here it's just annoying for you that it's returned as a dictionary rather than list? I'm open to providing a shortcut on the returned object to "listify" it more easily, but transforming it to a list can be done pretty easily without making reference the individual keys: from pyiron_workflow import Workflow
@Workflow.wrap_as.function_node()
def multiple_returns(a, b, c):
return a+1, b+2, c+3
wf = Workflow("io_demo")
wf.node = multiple_returns()
out = wf(node__a=0, node__b=1, node__c=2)
print(
"Returned to list:",
list(out.values())
)
>>> Returned to list: [1, 3, 5]
# or access it later
print(
"Workflow output dict to list",
list(wf.outputs.to_value_dict().values())
)
>>> Workflow output dict to list [1, 3, 5] Is that sufficient?
Working with .py files should be totally fine! The I copied my example above into a .py script and added Like the conversion to a list, I think there's probably tweaks we can make so that the process there is smoother, but I hope that at least is doing the job you're looking for. |
@liamhuber THANKS for the fast and compete answer I currently use steps as and that is amazing wf.step3 = step(storage, sample, 'sem', {'voltage':'30'}) Return values via .values() & list() is better but not ideal. But it works. Draw works great:
But the greatest issue for me is the design:
|
I'm glad someone's using it 😂
Great!
I opened a separate issue for this (#40). A shortcut will show up eventually in a future release.
The 90's are back baby! 🤣 But seriously, the left-right gradients are actually intentional to help distinguish input from output so I wouldn't want to get rid of those without some other visual queue in mind; the up-down gradients are just me showing my age I guess, haha. The aesthetic feedback is certainly welcome, but pretty low on my priority list so for now just hum the Friends theme and try to tolerate it 😉 For the more functional changes I'll apply at little higher priority although there are some core functionality changes to get out of the way first; I opened a separate issue so I don't lost track of it (#41).
Yeah, this is a real issue. In earlier iterations, things were actually extremely greedy: nodes always pushed their data off downstream, and also nodes always updated their output whenever they got new input (and all their input was of valid type). Of course not every node could be this way, because some were expensive and you didn't want them running all the time. So then we had this combination of "fast" and "slow" nodes. Joerg and I have discussed it lots, and ultimately we settled on a fully-delayed framework, where you can instantiate, inspect, and give new input to nodes and they don't run unless they receive some sort of explicit instruction to do so. AFAIK this is similar behaviour to DASK and most (but not all) other frameworks. I really do think this is the best choice and don't anticipate going back and changing it. One thing (my current primary goal) is to get a While I don't want to switch from a delayed to a greedy paradigm, I do see room to add something like a from pyiron_workflow import Workflow
@Workflow.wrap_as.function_node(run_on_instantiation=True)
def update_immediately(x=0, y=1):
return x+1, y+2
default_aggressive = update_immediately(y=3)
print(default_aggressive.outputs.to_value_dict())
>>> {"x+1": 1, "y+2": 5}
# Or
@Workflow.wrap_as.function_node()
def normal(x=0, y=1):
return x-1, y-2
explicit_instruction_to_be_agressive = normal(x=10, run_on_instantiation=True)
print(explicit_instruction_to_be_agressive.outputs.to_value_dict())
>>> {"x-1": 9, "y-2": -1} Would that be satisfactory? |
That would be very great and fully satisfactory. I fully understand why you want to have delayed execution as default and that it is almost essential for long duration calculations. Colors: of course they are low priority, I just have to give you a hard time. Thanks |
Super! I've opened the final item as a separate issue in #42. Now that these are all broken into smaller tasks, I'll close this. |
Joerg and Sarath introduced me to the workflow engine. Very nice work and useful. Below are some feedback that you might consider along with my example
could become one line:
Full example (I can supply the Storage and Sample classes on request)
The text was updated successfully, but these errors were encountered: