Skip to content

Commit

Permalink
Incomplete: First try at adding ipynb support to gustaf. Is not worki…
Browse files Browse the repository at this point in the history
…ng yet fully. Please check out the notebook in the examples folder.
  • Loading branch information
clemens-fricke committed Dec 15, 2023
1 parent a7aa793 commit e7fd963
Show file tree
Hide file tree
Showing 3 changed files with 280 additions and 9 deletions.
159 changes: 159 additions & 0 deletions examples/ipynb/show_boxes.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import gustaf as gus\n",
"import vedo\n",
"vedo.settings.default_backend = \"k3d\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mesh_faces_box = gus.create.faces.box(\n",
" bounds=[[0, 0], [2, 2]], resolutions=[2, 3]\n",
")\n",
"a = mesh_faces_box.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Volumes creates an error since vedo does something funny with UGrid when k3d is the backend. It might be an error introduced after they switched ugrid in one of the prior versions."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mesh_volumes_box = gus.create.volumes.box(\n",
" bounds=[[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]], resolutions=[2, 3, 4]\n",
" )\n",
"mesh_volumes_box.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mesh_faces_triangle = gus.create.faces.box(\n",
" bounds=[[0, 0], [2, 2]],\n",
" resolutions=[3, 3],\n",
" simplex=True,\n",
" backslash=False,\n",
")\n",
"mesh_faces_triangle.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mesh_faces_triangle_bs = gus.create.faces.box(\n",
" bounds=[[0, 0], [2, 2]],\n",
" resolutions=[3, 3],\n",
" simplex=True,\n",
" backslash=True,\n",
")\n",
"mesh_faces_triangle_bs.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gus.show(\n",
" [\"faces-box\", mesh_faces_box],\n",
" # [\"volumes-box\", mesh_volumes_box],\n",
" [\"faces-triangle\", mesh_faces_triangle],\n",
" [\"faces-triangle-backslash\", mesh_faces_triangle_bs],\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import splinepy"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def CubeLinear(origin, length):\n",
" origin_length = origin + length\n",
" return splinepy.Bezier(degrees=[1] * 3, control_points=[[origin, origin, origin], [origin_length, origin, origin], [origin, origin_length, origin], [origin_length, origin_length, \\\n",
" origin], [origin, origin, origin_length], [origin_length, origin, origin_length], [origin, origin_length, origin_length], [origin_length, origin_length, \\\n",
" origin_length]])\n",
"\n",
"length_center, length_corner = 0.2, 0.1\n",
"cube_center, cube_corner = CubeLinear(origin=0.5, length=length_center), CubeLinear(origin=1.0, length=-length_corner)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following works but looks very stupidly since the knot vector points and control points are shown much bigger than they should."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gus.show([\"cube-center\", cube_center], [\"cube-corner\", cube_corner])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "gustaf-main",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
58 changes: 49 additions & 9 deletions gustaf/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import numpy as np

from gustaf import utils
from gustaf.utils.notebook_helper import K3DPlotterN

# @linux it raises error if vedo is imported inside the function.
try:
Expand Down Expand Up @@ -34,6 +35,19 @@ def __call__(self, *args, **kwargs):
sys.modules[__name__].__class__ = _CallableShowDotPy


def is_ipython() -> bool:
"""Returns True if the current environment is IPython.
Check if the code is run in a notebook.
"""
try:
from IPython import get_ipython

return get_ipython() is not None
except ImportError:
return False


def show(
*args,
**kwargs,
Expand Down Expand Up @@ -82,14 +96,17 @@ def cam_tuple_to_list(dict_cam):

# get plotter
if plt is None:
plt = vedo.Plotter(
N=N,
sharecam=False,
offscreen=offs,
size=size,
title=title,
bg=background,
)
if is_ipython():
plt = K3DPlotterN(N, size, background)
else:
plt = vedo.Plotter(
N=N,
sharecam=False,
offscreen=offs,
size=size,
title=title,
bg=background,
)

else:
# check if plt has enough Ns
Expand Down Expand Up @@ -171,6 +188,9 @@ def cam_tuple_to_list(dict_cam):
# offscreen=offs,
)

if is_ipython():
plt.display()
return
if interact and not offs:
# only way to ensure memory is released
clear_vedo_plotter(plt, np.prod(plt.shape))
Expand All @@ -179,13 +199,33 @@ def cam_tuple_to_list(dict_cam):
# It seems to leak some memory, but here it goes.
plt.close() # if i close it, this cannot be reused...
plt = None

if return_show_list:
return (plt, list_of_showables)
else:
return plt


def show_notebook(
*args,
**kwargs,
):
elements_to_show = []
for element in args:
if hasattr(element, "showable"):
elements_to_show.append([element.showable(**kwargs)])
elif isinstance(element, list):
sub_list = []
for sub_element in element:
if hasattr(sub_element, "showable"):
sub_list.append(sub_element.showable(**kwargs))
else:
raise TypeError(
"Only gustaf objects can be shown in notebook"
)
else:
raise TypeError("For vedo_show, only list or dict is valid input")


def make_showable(obj, as_dict=False, **kwargs):
"""Generates a vedo obj based on `kind` attribute from given obj, as well
as show_options.
Expand Down
72 changes: 72 additions & 0 deletions gustaf/utils/notebook_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import numpy as np
import vedo
from IPython.display import display
from ipywidgets import GridspecLayout


def get_shape(N, x, y):
"""Taken verbatim from vedo plotter class.
Args:
N (_type_): _description_
x (_type_): _description_
y (_type_): _description_
Returns:
_type_: _description_
"""
nx = int(np.sqrt(int(N * y / x) + 1))
ny = int(np.sqrt(int(N * x / y) + 1))
lm = [
(nx, ny),
(nx, ny + 1),
(nx - 1, ny),
(nx + 1, ny),
(nx, ny - 1),
(nx - 1, ny + 1),
(nx + 1, ny - 1),
(nx + 1, ny + 1),
(nx - 1, ny - 1),
]
ind, minl = 0, 1000
for i, m in enumerate(lm):
l_something = m[0] * m[1]
if N <= l_something < minl:
ind = i
minl = l_something
return lm[ind]


class K3DPlotterN(GridspecLayout):
def __init__(self, N, size, background=0xFFFFFF):
self.N = N
self.x, self.y = get_shape(N, *(2160, 1440))
self.shape = (self.x, self.y)
super().__init__(self.x, self.y)
self.renderers = []
for _ in range(N):
self.renderers.append(
vedo.Plotter(
size=size,
bg=background,
)
)

def _at_get_location(self, N):
if self.x * self.y < N:
return (self.x - 1, self.y - 1)
return (N // (self.y + 1), N % self.y)

def show(self, list_of_showables, at, interactive, camera):
self[self._at_get_location(at)] = self.renderers[at].show(
list_of_showables,
interactive=interactive,
camera=camera,
# offscreen=offscreen,
)

def display(self):
display(self)

def clear(*args, **kwargs):
pass

0 comments on commit e7fd963

Please sign in to comment.