S
Solara

general

Blender with Solara

JMJan-Hendrik Müller10/4/2023
JMJan-Hendrik Müller10/4/2023
A bit of additional context: Radamés Ajna was trying the same thing with Gradio and said: "It won't work well on a shared web env due to a single Blender context, so set I set Gradio concurrency_count=1." https://twitter.com/radamar/status/1701348276853960908 Is this the same reason here? Also, When I work locally, for each notebook a separate Python symbol is showing in my task bar:
No description
JMJan-Hendrik Müller10/4/2023
and last but not least, here's the link to my project: https://huggingface.co/spaces/kolibril13/blender-with-solara
MMaartenBreddels10/4/2023
yes, i think the same is happening in solara
JMJan-Hendrik Müller10/4/2023
Yes, the code is interacting and modifying the global state of the Blender scene via the bpy module like this
import bpy
# ...
light = bpy.data.objects["Light"]
light.location = (1, 0, 2)
import bpy
# ...
light = bpy.data.objects["Light"]
light.location = (1, 0, 2)
MMaartenBreddels10/4/2023
is there no way around that? there is no 'context' or 'scene' object to isolatie all the settings
JMJan-Hendrik Müller10/4/2023
I'm really new to that API, I'll check! And another question to another scenario: Now, I've got a new solara project with only one notebook that renders a protein. It runs totally fine in a normal notebook environment (see screen recording). But as soon as I run solara run pages/. and click the "Start Rendering" Button in my Solara App, I get the error. Any ideas why this might happen?
Traceback (most recent call last):
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/reacton/core.py", line 1647, in _render
root_element = el.component.f(*el.args, **el.kwargs)
File "/Users/jan-hendrik/projects/blender-with-solara/pages/03_molecule.ipynb input cell 1", line 85, in Page
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/molecularnodes/load.py", line 116, in molecule_rcsb
nodes.create_starting_node_tree(
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/molecularnodes/nodes.py", line 349, in create_starting_node_tree
node_color_set = add_custom_node_group(node_mod, 'MN_color_set', [200, 0])
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/molecularnodes/nodes.py", line 122, in add_custom_node_group
append(node_name, link=link)
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/molecularnodes/nodes.py", line 43, in append
bpy.ops.wm.append(
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/bpy/3.6/scripts/modules/bpy/ops.py", line 113, in __call__
ret = _op_call(self.idname_py(), None, kw)
RuntimeError: Operator bpy.ops.wm.append.poll() failed, context is incorrect
Traceback (most recent call last):
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/reacton/core.py", line 1647, in _render
root_element = el.component.f(*el.args, **el.kwargs)
File "/Users/jan-hendrik/projects/blender-with-solara/pages/03_molecule.ipynb input cell 1", line 85, in Page
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/molecularnodes/load.py", line 116, in molecule_rcsb
nodes.create_starting_node_tree(
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/molecularnodes/nodes.py", line 349, in create_starting_node_tree
node_color_set = add_custom_node_group(node_mod, 'MN_color_set', [200, 0])
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/molecularnodes/nodes.py", line 122, in add_custom_node_group
append(node_name, link=link)
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/molecularnodes/nodes.py", line 43, in append
bpy.ops.wm.append(
File "/Users/jan-hendrik/projects/blender-with-solara/.venv/lib/python3.10/site-packages/bpy/3.6/scripts/modules/bpy/ops.py", line 113, in __call__
ret = _op_call(self.idname_py(), None, kw)
RuntimeError: Operator bpy.ops.wm.append.poll() failed, context is incorrect
JMJan-Hendrik Müller10/4/2023
JMJan-Hendrik Müller10/4/2023
MMaartenBreddels10/4/2023
seems like there is some default context in jupyter
JMJan-Hendrik Müller10/4/2023
yes, I think so too! Can I get this default context somehow to solara?
MMaartenBreddels10/4/2023
i don't know how their notebook integration works can't even find their github pages, or anything about notebook integration is this very new?
JMJan-Hendrik Müller10/4/2023
It's just a few months since the blender py module bpy is pip-installable. I achieved the notebook integration only a few weeks ago via
import bpy
from IPython.display import display, Image

path = "test.png"
bpy.context.scene.render.resolution_x = 500
bpy.context.scene.render.resolution_y = 200
bpy.ops.render.render()
bpy.data.images["Render Result"].save_render(filepath=path)
display(Image(filename=path))
import bpy
from IPython.display import display, Image

path = "test.png"
bpy.context.scene.render.resolution_x = 500
bpy.context.scene.render.resolution_y = 200
bpy.ops.render.render()
bpy.data.images["Render Result"].save_render(filepath=path)
display(Image(filename=path))
So there's no documentation about blender in notebook around yet. Converting this to a solara component works fine both in notebook and in the solara server:
import bpy
from IPython.display import display, Image

import solara

@solara.component
def Page():
path = "test.png"
bpy.context.scene.render.resolution_x = 500
bpy.context.scene.render.resolution_y = 200
bpy.ops.render.render()
bpy.data.images["Render Result"].save_render(filepath=path)
display(Image(filename=path))
Page()
import bpy
from IPython.display import display, Image

import solara

@solara.component
def Page():
path = "test.png"
bpy.context.scene.render.resolution_x = 500
bpy.context.scene.render.resolution_y = 200
bpy.ops.render.render()
bpy.data.images["Render Result"].save_render(filepath=path)
display(Image(filename=path))
Page()
Then, importing the molecule model works fine in Jupyter, but fails in the solara server with the "context is incorrect" error.
import bpy
from IPython.display import display, Image

import solara
import molecularnodes as mn

@solara.component
def Page():
path = "test.png"
mn.load.molecule_rcsb('6N2Y') # <- this line causes the error 🐛
bpy.context.scene.render.resolution_x = 500
bpy.context.scene.render.resolution_y = 200
bpy.ops.render.render()
bpy.data.images["Render Result"].save_render(filepath=path)
display(Image(filename=path))
Page()
import bpy
from IPython.display import display, Image

import solara
import molecularnodes as mn

@solara.component
def Page():
path = "test.png"
mn.load.molecule_rcsb('6N2Y') # <- this line causes the error 🐛
bpy.context.scene.render.resolution_x = 500
bpy.context.scene.render.resolution_y = 200
bpy.ops.render.render()
bpy.data.images["Render Result"].save_render(filepath=path)
display(Image(filename=path))
Page()
JMJan-Hendrik Müller10/4/2023
this is deftly not related to solara, when I try to run this script with Gradio, I get the same error https://github.com/radames/Gradio-Blender-bpy/issues/1 so I will reach out and ask in the blender community next 🙂
GitHub
Making molecularnodes a stand-alone web app with gradio 🧬 · Issue #...
hi @radames thanks for creating this project, which converts python blender pipelines to stand-alone web apps. I want to share an idea for a follow-up project: @BradyAJohnston just created "mo...
MMaartenBreddels10/4/2023
keep me up to date on this!
JMJan-Hendrik Müller10/5/2023
Hi @MaartenBreddels, the issue is solved now and was related to bpy context handling, the full conversation that solved this issue is here: https://github.com/radames/Gradio-Blender-bpy/issues/1 I've now hosted a solara app on huggingface (code is only a very quick write-up, nothing too pretty): https://huggingface.co/spaces/kolibril13/solara-bpy The solara app is very performant when I run it on my MAC M1 (rendering the molecule takes only 1 second). Rendering on the huggingface free plan is a bit slower, takes 40 seconds. Here's a screenshot:
JMJan-Hendrik Müller10/5/2023
No description
MMaartenBreddels10/5/2023
very cool i couldn't install it, because it needs a specific python version you might be interested in this 'pattern':
import solara
from IPython.display import Image, display

light_position = solara.reactive(3)
do_render = solara.reactive(False)

@solara.component
def Page():

def render():
if do_render.value:
import time
time.sleep(2)
# do you rendering here
return "https://s.yimg.com/ny/api/res/1.2/djPKKfbQP1PAJO2ZdPzDPw--/YXBwaWQ9aGlnaGxhbmRlcjt3PTk2MDtoPTcyMDtjZj13ZWJw/https://s.yimg.com/os/en_US/News/BGR_News/funny-cat.jpg"
result = solara.use_thread(render, [do_render.value])
if not do_render.value:
solara.Button("Start Rendering", on_click=lambda: do_render.set(True))
else:
if result.state == solara.ResultState.RUNNING:
solara.Info("Rendering in progress...")
solara.ProgressLinear()
elif result.state == solara.ResultState.ERROR:
solara.Error("Rendering failed!: %s" % result.error)
elif result.state == solara.ResultState.FINISHED:
with solara.Column():
solara.Success("Rendering complete. ")
print(result.value)
# workaround for https://github.com/widgetti/solara/pull/267
if result.value:
display(Image(result.value))
# display(Image(result.value))
# solara.Image(result.value)
import solara
from IPython.display import Image, display

light_position = solara.reactive(3)
do_render = solara.reactive(False)

@solara.component
def Page():

def render():
if do_render.value:
import time
time.sleep(2)
# do you rendering here
return "https://s.yimg.com/ny/api/res/1.2/djPKKfbQP1PAJO2ZdPzDPw--/YXBwaWQ9aGlnaGxhbmRlcjt3PTk2MDtoPTcyMDtjZj13ZWJw/https://s.yimg.com/os/en_US/News/BGR_News/funny-cat.jpg"
result = solara.use_thread(render, [do_render.value])
if not do_render.value:
solara.Button("Start Rendering", on_click=lambda: do_render.set(True))
else:
if result.state == solara.ResultState.RUNNING:
solara.Info("Rendering in progress...")
solara.ProgressLinear()
elif result.state == solara.ResultState.ERROR:
solara.Error("Rendering failed!: %s" % result.error)
elif result.state == solara.ResultState.FINISHED:
with solara.Column():
solara.Success("Rendering complete. ")
print(result.value)
# workaround for https://github.com/widgetti/solara/pull/267
if result.value:
display(Image(result.value))
# display(Image(result.value))
# solara.Image(result.value)
JMJan-Hendrik Müller10/5/2023
oh yes, it runs only on python3.10
python3.10 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
solara run ./pages
python3.10 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
solara run ./pages
should work I've just tested your snippet, what a cute surprise 🐱✨ Very useful indeed! Is there also a way to show a progress bar to run from 0 to 2 seconds? All renderings will approx. take the same time, so that would give the user even a better estimate how to long to wait.
MMaartenBreddels10/5/2023
hmm, not easily
JMJan-Hendrik Müller10/5/2023
also not that important⏳ And another thought: ipyMolecularNodes is a proof of concept that blender models can be turned into notebooks for the scientific python visualization workflow. That means that for every blender model ever created, and all future models that will be created, this is theoretically possible as well. With solara, these notebooks can then even be turned into standalone-zero-install web apps. I don't know yet where this can be of practical use, but I see huge potential for this pipeline!

Looking for more? Join the community!

Want results from more Discord servers?
Add your server
Recommended Posts
would be very happy to be a guinnea pigwould be very happy to be a guinnea pig 😄Which version of lab running pip installWhich version of lab? running !pip install will install it in the kernel environment, if the lab serThanks how could I programatically setThanks ! how could I programatically set theme from Python side ?it seems to be functional not sure Iit seems to be functional. not sure I understand the downside of my current approach. but fixing any3 what s the best way to implement `push3. what's the best way to implement `push notification` ? is it something like this ? and is it run 2 when I create a module level reactive2. when I create a module level reactive var like `x = solara.reactive(None)`, is it application widcouple of questions around sessioncouple of questions around session management: 1. I found Solara manages session via cookie which isI m not sure what you mean but changingI'm not exactly sure what you mean, but changing the value from the backend would look something likhey solara team looking into statehey solara team looking into state documentation. It seems solara.reactive is session based as in ifhope to know when we will get this fixedhope to know when we will get this fixed. I am developing some demo with Solara and don't want to seThe timer thread is an infinte loop ThatThe timer thread is an infinte loop. That's the only loop I know of. And the timer isn't a problem I m trying to run Solara as Embedding inI'm trying to run Solara as "Embedding in an existing Starlette application" and when I go to `/solaAren't all these the responsibility of the browser to fetch stuff from the CDN?Good afternoon! Can Solara run on a read-only file system? I tried running it on AWS Lambda and it cwhat did you use for thatwhat did you use for that?btw working with Layout and routes was abtw, working with Layout and routes was a pain in my case. One problem was it didn't use the LayoQuestion regarding the `component vue` IQuestion regarding the `component_vue` - I'm trying to create a Box component that will auto scroHi I’ve been trying to add backgroundHi. I’ve been trying to add background image to my page. I created a CSS.py script which contain a tAnother question I m trying to attachAnother question, I'm trying to attach `keydown` listener to TextArea (so that I can submit when "EnI m using IntelliJI'm using IntelliJ`````` from typing import List, cast import plotly import solara df = plotly.data.gapminder() column