mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-25 21:40:33 +05:00
wip - move code from webgui_jupyter_widgets project to Netgen
This commit is contained in:
parent
b808d84957
commit
75372b0695
@ -20,7 +20,7 @@ install(FILES
|
|||||||
__main__.py __init__.py
|
__main__.py __init__.py
|
||||||
meshing.py csg.py geom2d.py stl.py gui.py NgOCC.py occ.py
|
meshing.py csg.py geom2d.py stl.py gui.py NgOCC.py occ.py
|
||||||
read_gmsh.py read_meshio.py
|
read_gmsh.py read_meshio.py
|
||||||
webgui.py
|
webgui.py jupyter.py
|
||||||
DESTINATION ${NG_INSTALL_DIR_PYTHON}/${NG_INSTALL_SUFFIX}
|
DESTINATION ${NG_INSTALL_DIR_PYTHON}/${NG_INSTALL_SUFFIX}
|
||||||
COMPONENT netgen
|
COMPONENT netgen
|
||||||
)
|
)
|
||||||
|
103
python/jupyter.py
Normal file
103
python/jupyter.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from IPython.display import HTML, DisplayHandle, Javascript, display
|
||||||
|
|
||||||
|
_id = 0 # counter for unique id for each generated div element
|
||||||
|
|
||||||
|
# VSCode has a strange meaning of "vh" in jupyter notebooks, use pixels instead
|
||||||
|
_default_height = "500px" if "VSCODE_PID" in os.environ else "50vh"
|
||||||
|
|
||||||
|
_webgui_loaded = False
|
||||||
|
|
||||||
|
|
||||||
|
def load_webgui(url: str = "", embed_code: bool = False):
|
||||||
|
global _webgui_loaded
|
||||||
|
if _webgui_loaded:
|
||||||
|
return
|
||||||
|
_webgui_loaded = True
|
||||||
|
|
||||||
|
url = url or "https://cdn.jsdelivr.net/npm/webgui@0.2.38/dist/webgui.js"
|
||||||
|
|
||||||
|
if embed_code:
|
||||||
|
if url.startswith("http"):
|
||||||
|
webgui_code = requests.get(url).text
|
||||||
|
else:
|
||||||
|
with open(url, "r") as f:
|
||||||
|
webgui_code = f.read()
|
||||||
|
display(HTML(f"<script>{webgui_code}</script>"))
|
||||||
|
else:
|
||||||
|
display(HTML(f"<script src={url}> </script>"))
|
||||||
|
|
||||||
|
|
||||||
|
def render(
|
||||||
|
data, width="100%", height=_default_height, handle: DisplayHandle | None = None
|
||||||
|
):
|
||||||
|
load_webgui()
|
||||||
|
if handle is None:
|
||||||
|
global _id
|
||||||
|
_id += 1
|
||||||
|
id = _id
|
||||||
|
else:
|
||||||
|
id = handle.display_id.split("_")[-1]
|
||||||
|
|
||||||
|
el_id = f"_webgui_root_{id}"
|
||||||
|
|
||||||
|
js_code = _render_js_template.replace("{{data}}", json.dumps(data))
|
||||||
|
js_code = js_code.replace("{{id}}", str(id))
|
||||||
|
js_code = js_code.replace("{{el_id}}", el_id)
|
||||||
|
if handle:
|
||||||
|
# this is a redraw call
|
||||||
|
handle.update(Javascript(js_code))
|
||||||
|
else:
|
||||||
|
# this is a first draw call -> create the root div element for the webgui
|
||||||
|
display(
|
||||||
|
HTML(
|
||||||
|
f'<div class="webgui-widget" id={el_id} style="position: relative; width: {width}; height:{height};" />'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return display(Javascript(js_code), display_id=f"webgui_render_{id}")
|
||||||
|
|
||||||
|
|
||||||
|
_render_js_template = """
|
||||||
|
{
|
||||||
|
if(window._webgui_scenes === undefined) {
|
||||||
|
window._webgui_scenes = {};
|
||||||
|
}
|
||||||
|
const waitForWebgui = (callback, counter) => {
|
||||||
|
counter = counter || 0;
|
||||||
|
if (window.webgui) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
if (counter < 20) {
|
||||||
|
setTimeout(() => {
|
||||||
|
waitForWebgui(callback, counter + 1);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("Error: Webgui not loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const draw = () => {
|
||||||
|
const data = JSON.parse(`{{data}}`);
|
||||||
|
let scene = window._webgui_scenes[{{id}}];
|
||||||
|
// console.log("have data, scene = ", scene);
|
||||||
|
if(scene === undefined) {
|
||||||
|
console.log("init scene");
|
||||||
|
const root = document.getElementById("{{el_id}}");
|
||||||
|
console.log("root element", root);
|
||||||
|
scene = new webgui.Scene();
|
||||||
|
scene.init(root, data);
|
||||||
|
window._webgui_scenes[{{id}}] = scene;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
scene.updateRenderData(data);
|
||||||
|
}
|
||||||
|
// console.log("scene", scene);
|
||||||
|
}
|
||||||
|
waitForWebgui(draw);
|
||||||
|
}
|
||||||
|
"""
|
@ -1,17 +1,17 @@
|
|||||||
import math
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from time import time
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import webgui_jupyter_widgets
|
__IPYTHON__
|
||||||
from webgui_jupyter_widgets import BaseWebGuiScene, WebGuiDocuWidget
|
_IN_IPYTHON = True
|
||||||
import webgui_jupyter_widgets.widget as wg
|
|
||||||
except ImportError:
|
|
||||||
class BaseWebGuiScene:
|
|
||||||
pass
|
|
||||||
|
|
||||||
wg = None
|
from .jupyter import render as _render
|
||||||
|
except NameError:
|
||||||
|
_IN_IPYTHON = False
|
||||||
|
|
||||||
|
def _render(*args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
def encodeData( data, dtype=None, encoding='b64' ):
|
def encodeData( data, dtype=None, encoding='b64' ):
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -25,18 +25,8 @@ def encodeData( data, dtype=None, encoding='b64' ):
|
|||||||
else:
|
else:
|
||||||
raise RuntimeError("unknown encoding" + str(encoding))
|
raise RuntimeError("unknown encoding" + str(encoding))
|
||||||
|
|
||||||
from packaging.version import parse
|
|
||||||
|
|
||||||
import netgen.meshing as ng
|
import netgen.meshing as ng
|
||||||
|
|
||||||
if wg is not None and parse(webgui_jupyter_widgets.__version__) >= parse("0.2.18"):
|
|
||||||
_default_width = None
|
|
||||||
_default_height = None
|
|
||||||
else:
|
|
||||||
_default_width = "100%"
|
|
||||||
_default_height = "50vh"
|
|
||||||
|
|
||||||
|
|
||||||
_registered_draw_types = {}
|
_registered_draw_types = {}
|
||||||
|
|
||||||
|
|
||||||
@ -217,7 +207,7 @@ def GetData(mesh, args, kwargs):
|
|||||||
d[name] = pnew
|
d[name] = pnew
|
||||||
return d
|
return d
|
||||||
|
|
||||||
class WebGLScene(BaseWebGuiScene):
|
class WebGLScene:
|
||||||
class Widget:
|
class Widget:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.value = {}
|
self.value = {}
|
||||||
@ -228,6 +218,7 @@ class WebGLScene(BaseWebGuiScene):
|
|||||||
self.args = args
|
self.args = args
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
self.encoding = "b64"
|
self.encoding = "b64"
|
||||||
|
self.handle = None
|
||||||
|
|
||||||
def Redraw(self, *args, **kwargs):
|
def Redraw(self, *args, **kwargs):
|
||||||
if args or kwargs:
|
if args or kwargs:
|
||||||
@ -238,7 +229,8 @@ class WebGLScene(BaseWebGuiScene):
|
|||||||
self.obj = new_scene.obj
|
self.obj = new_scene.obj
|
||||||
self.args = new_scene.args
|
self.args = new_scene.args
|
||||||
self.kwargs = new_scene.kwargs
|
self.kwargs = new_scene.kwargs
|
||||||
super().Redraw()
|
_render(self.GetData(), handle=self.handle)
|
||||||
|
# super().Redraw()
|
||||||
|
|
||||||
def GetData(self, set_minmax=True):
|
def GetData(self, set_minmax=True):
|
||||||
self.kwargs["encoding"] = self.encoding
|
self.kwargs["encoding"] = self.encoding
|
||||||
@ -389,8 +381,6 @@ def _get_draw_default_args():
|
|||||||
settings={},
|
settings={},
|
||||||
fullscreen=False,
|
fullscreen=False,
|
||||||
scale=1.0,
|
scale=1.0,
|
||||||
width=_default_width,
|
|
||||||
height=_default_height,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -399,27 +389,29 @@ def Draw(obj, *args, show=True, **kwargs):
|
|||||||
kwargs_with_defaults.update(kwargs)
|
kwargs_with_defaults.update(kwargs)
|
||||||
|
|
||||||
scene = WebGLScene(obj, args, kwargs_with_defaults)
|
scene = WebGLScene(obj, args, kwargs_with_defaults)
|
||||||
if show and wg is not None and wg._IN_IPYTHON:
|
scene.handle = _render(scene.GetData())
|
||||||
if wg._IN_GOOGLE_COLAB:
|
|
||||||
from IPython.display import display, HTML
|
|
||||||
|
|
||||||
html = scene.GenerateHTML()
|
|
||||||
display(HTML(html))
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
import webgui_jupyter_widgets as wjw
|
|
||||||
from packaging.version import parse
|
|
||||||
|
|
||||||
# render scene using widgets.DOMWidget
|
|
||||||
if parse(wjw.__version__) < parse("0.2.15"):
|
|
||||||
scene.Draw()
|
|
||||||
else:
|
|
||||||
scene.Draw(
|
|
||||||
kwargs_with_defaults["width"], kwargs_with_defaults["height"]
|
|
||||||
)
|
|
||||||
if "filename" in kwargs_with_defaults:
|
|
||||||
scene.GenerateHTML(filename=kwargs_with_defaults["filename"])
|
|
||||||
return scene
|
return scene
|
||||||
|
# if show and wg is not None and wg._IN_IPYTHON:
|
||||||
|
# if wg._IN_GOOGLE_COLAB:
|
||||||
|
# from IPython.display import display, HTML
|
||||||
|
#
|
||||||
|
# html = scene.GenerateHTML()
|
||||||
|
# display(HTML(html))
|
||||||
|
# return
|
||||||
|
# else:
|
||||||
|
# import webgui_jupyter_widgets as wjw
|
||||||
|
# from packaging.version import parse
|
||||||
|
#
|
||||||
|
# # render scene using widgets.DOMWidget
|
||||||
|
# if parse(wjw.__version__) < parse("0.2.15"):
|
||||||
|
# scene.Draw()
|
||||||
|
# else:
|
||||||
|
# scene.Draw(
|
||||||
|
# kwargs_with_defaults["width"], kwargs_with_defaults["height"]
|
||||||
|
# )
|
||||||
|
# if "filename" in kwargs_with_defaults:
|
||||||
|
# scene.GenerateHTML(filename=kwargs_with_defaults["filename"])
|
||||||
|
# return scene
|
||||||
|
|
||||||
async def _MakeScreenshot(data, png_file, width=1200, height=600):
|
async def _MakeScreenshot(data, png_file, width=1200, height=600):
|
||||||
"""Uses playwright to make a screenshot of the given html file."""
|
"""Uses playwright to make a screenshot of the given html file."""
|
||||||
|
Loading…
Reference in New Issue
Block a user