bernhard-42 / jupyter-cadquery

An extension to render cadquery objects in JupyterLab via pythreejs
Apache License 2.0
312 stars 44 forks source link

Preview: Juypter CadQuery now has a Viewer component for debugging in IDEs #42

Closed bernhard-42 closed 3 years ago

bernhard-42 commented 3 years ago

This is a beta version (beta1) of the CadQuery viewer for IDEs I talked about earlier.

If you want to give it a try, happy to get feedback.

Installation

It can be installed in an existing conda environment

pip install git+https://github.com/bernhard-42/jupyter-cadquery.git@viewer2

However, since it is quite young, I'd recommend to try it in a fresh conda environment with CadQuery 2.1 being installed:

conda create -n jcv python=3.8
conda activate jcv

conda install pywin32  # Windows users only
conda install -c conda-forge -c cadquery cadquery=2.1

pip install git+https://github.com/bernhard-42/jupyter-cadquery.git@viewer2

pip install git+https://github.com/bernhard-42/cadquery-massembly  # for the animated examples

Test from the terminal

Starting (on Mac, Linux and Windows)

jcv -w 800 -h 600

image

As a simple test add the following code to test.py:

import cadquery as cq
from jupyter_cadquery.viewer.client import show

box = cq.Workplane().box(1, 1, 1).faces(">Z").hole(0.6).edges().fillet(0.05)
cyl = cq.Workplane().circle(0.1).extrude(1)

show(box, cyl, axes=True, transparent=True)

viewer

Debugging session with dark theme

jcv -d -w 650 -h 400

debugging

Jojain commented 3 years ago

Thanks for the work it looks amazing.

I've tried to run it by typing jcv in fresh conda env with only cadquery and your branch but it fails to launch. I get an import error for import win32api

EDIT : I tried to install the regular jupyter-cadquery in another new conda env and I had the same error so I assume it's something wrong on my side. I manually installed the lib via conda install pywin32 and It solved the problem for the regular jupyter-cadquery and your branch but then for the viewer branch I then have the following error :

[Voila] Using C:\Users\Romain\AppData\Local\Temp to store connection files
[Voila] Storing connection files in C:\Users\Romain\AppData\Local\Temp\voila_a2x4nfhb.
[Voila] Serving static files from d:\programmes\miniconda\envs\jcv\lib\site-packages\voila\static.
[Voila] Voilà is running at:
http://localhost:8866/
[Voila] WARNING | Notebook viewer.ipynb is not trusted
[Voila] WARNING | Could not find a kernel named 'jvc', will use  '597585c0-bc20-4126-936a-8287d64ef80b'
[Voila] Kernel started: c54f9ac8-91c1-410c-9278-c4953ccb5324
[Voila] ERROR | Error at server while executing cell: {'cell_type': 'code', 'execution_count': 1, 'id': '9e3173e3-0ad5-4da8-b614-83cf03de2906', 'metadata': {'trusted': False, 'execution': {'iopub.status.busy': '2021-05-06T18:05:24.924224Z', 'iopub.execute_input': '2021-05-06T18:05:24.925249Z', 'shell.execute_reply': '2021-05-06T18:05:24.983065Z', 'iopub.status.idle': '2021-05-06T18:05:24.984084Z'}}, 'outputs': [{'output_type': 'error', 'ename': 'ModuleNotFoundError', 'evalue': "No module named 'jupyter_cadquery'", 'traceback': ['\x1b[1;31m---------------------------------------------------------------------------\x1b[0m', '\x1b[1;31mModuleNotFoundError\x1b[0m                       Traceback (most recent call last)', '\x1b[1;32m<ipython-input-1-cf127186a9ab>\x1b[0m in \x1b[0;36m<module>\x1b[1;34m\x1b[0m\n\x1b[1;32m----> 1\x1b[1;33m \x1b[1;32mfrom\x1b[0m \x1b[0mjupyter_cadquery\x1b[0m\x1b[1;33m.\x1b[0m\x1b[0mviewer\x1b[0m\x1b[1;33m.\x1b[0m\x1b[0mserver\x1b[0m \x1b[1;32mimport\x1b[0m \x1b[0mstart_viewer\x1b[0m\x1b[1;33m\x1b[0m\x1b[1;33m\x1b[0m\x1b[0m\n\x1b[0m\x1b[0;32m      2\x1b[0m \x1b[0mstart_viewer\x1b[0m\x1b[1;33m(\x1b[0m\x1b[1;33m)\x1b[0m\x1b[1;33m\x1b[0m\x1b[1;33m\x1b[0m\x1b[0m\n', "\x1b[1;31mModuleNotFoundError\x1b[0m: No module named 'jupyter_cadquery'"]}], 'source': 'from jupyter_cadquery.viewer.server import start_viewer\nstart_viewer()'}
Traceback (most recent call last):
  File "d:\programmes\miniconda\envs\jcv\lib\site-packages\voila\handler.py", line 209, in _jinja_cell_generator
    output_cell = await task
  File "d:\programmes\miniconda\envs\jcv\lib\site-packages\voila\execute.py", line 69, in execute_cell
    result = await self.async_execute_cell(cell, cell_index, store_history)
  File "d:\programmes\miniconda\envs\jcv\lib\site-packages\nbclient\client.py", line 857, in async_execute_cell
    self._check_raise_for_error(cell, exec_reply)
  File "d:\programmes\miniconda\envs\jcv\lib\site-packages\nbclient\client.py", line 760, in _check_raise_for_error
    raise CellExecutionError.from_cell_and_msg(cell, exec_reply_content)
nbclient.exceptions.CellExecutionError: An error occurred while executing the following cell:
------------------
from jupyter_cadquery.viewer.server import start_viewer
start_viewer()
------------------

←[1;31m---------------------------------------------------------------------------←[0m
←[1;31mModuleNotFoundError←[0m                       Traceback (most recent call last)
←[1;32m<ipython-input-1-cf127186a9ab>←[0m in ←[0;36m<module>←[1;34m←[0m
←[1;32m----> 1←[1;33m ←[1;32mfrom←[0m ←[0mjupyter_cadquery←[0m←[1;33m.←[0m←[0mviewer←[0m←[1;33m.←[0m←[0mserver←[0m ←[1;32mimport←[0m ←[0mstart_viewer←[0m←[1;33m←[0m←[1;33m←[0m←[0m
←[0m←[0;32m      2←[0m ←[0mstart_viewer←[0m←[1;33m(←[0m←[1;33m)←[0m←[1;33m←[0m←[1;33m←[0m←[0m

←[1;31mModuleNotFoundError←[0m: No module named 'jupyter_cadquery'
ModuleNotFoundError: No module named 'jupyter_cadquery'

WARNING:tornado.general:403 GET /voila/files/favicon.ico (::1): File not whitelisted
WARNING:tornado.access:403 GET /voila/files/favicon.ico (::1) 1.00ms

I can import jupyter_cadquery from this env in a python interpreter and it works so I assume that the import in the jupyter notebook doesn't look where it should to find the lib.

I don't know that much about ipython kernel and stuff so I don't know what can happen

bernhard-42 commented 3 years ago

You could also just start jupyter lab in the environment where the new version is installed and paste the two lines

from jupyter_cadquery.viewer.server import start_viewer
start_viewer()

into a cell and execute it (voila just automates that) Does it find start_viewer?

bernhard-42 commented 3 years ago

A simpler test whether the installation worked would be

(jcv) C:\Users\bernhard>python
Python 3.8.8 (default, Apr 13 2021, 15:08:03) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.executable
'C:\\Users\\bernhard\\miniconda3\\envs\\jcv\\python.exe'
>>> from jupyter_cadquery.viewer.server import start_viewer
>>>

I am surprised that in your case a kernel 597585c0-bc20-4126-936a-8287d64ef80b is selected. Usually it should be python3 in a fresh environment. This is how it looks like for me:

(jcv) C:\Users\bernhard>jcv
[Voila] Using C:\Users\bernhard\AppData\Local\Temp to store connection files
[Voila] Storing connection files in C:\Users\bernhard\AppData\Local\Temp\voila__rfmrk1o.
[Voila] Serving static files from c:\users\bernhard\miniconda3\envs\jcv\lib\site-packages\voila\static.
[Voila] Voilà is running at:
http://localhost:8866/
[Voila] WARNING | Notebook viewer.ipynb is not trusted
[Voila] WARNING | Could not find a kernel named 'jvc', will use  'python3'
[Voila] Kernel started: 931fa6fa-c4a3-4ed0-adb3-4902a10b3d4e
WARNING:tornado.general:403 GET /voila/files/favicon.ico (::1): File not whitelisted
WARNING:tornado.access:403 GET /voila/files/favicon.ico (::1) 1.00ms
WARNING:tornado.general:403 GET /voila/files/voila/jupyter-threejs.js (::1): File not whitelisted
WARNING:tornado.access:403 GET /voila/files/voila/jupyter-threejs.js (::1) 0.00ms
WARNING:tornado.general:403 GET /voila/files/voila/jupyter_cadquery.js (::1): File not whitelisted
WARNING:tornado.access:403 GET /voila/files/voila/jupyter_cadquery.js (::1) 0.00ms
Jojain commented 3 years ago

It works when running it directly from jupyter lab! I've tried it with a more complex example and everything seems to run smoothly. If I call show several times it refresh the view and doesn't populate the view with several parts. I don't know if it's intended or if it's work in progress.

bernhard-42 commented 3 years ago

Nice! I will look into voila and its kernel issue, since that would be easier.

show works differently than show_object in CadQuery. You can give more than one object: show(obj1, obj1, ...). You can then in the view hide/show parts to better understand complex objects. If you use PartGroup and Parts from jupyter cadquery, you can also build hierarchies of objects and name and color them for the view (see an example in the Readme)

Would that help?

jmwright commented 3 years ago

@bernhard-42 I'm not understanding to how execute code. I have the viewer open, and you say above to add code to test.py. It looks in the gif like you're adding code in VS Code (maybe?), so I'm not sure how to make that work. Where is test.py located?

Jojain commented 3 years ago

@jmwright I think you can run the code test.py from wherever you want, if I understand it well, when you run your python script the show function send the data to the ipython kernel so it's displayed in jupyterlab.

For my case I got it working by running test.py from vscode in the conda env where jcv is installed after having started jupyterlab as explained by @bernhard-42

bernhard-42 commented 3 years ago

@Jojain correct. @jmwright The show function imported will tessellate the objects provided and then send the numpy arrays via zmq to the viewer. So you can call python test.py from the command line or run it in VSCode or any other editor from anywhere. You only need to use the python interpreter of the conda env you've installed the viewer into. The viewer is stateless, so you can even send (show) objects from different editor instances. If you set reset_camera=False, different calls to show will use the same angle to look at the object.

So basically, when the voila thing works (see below) you don't even see jupyter. And restarting the viewer simply is a browser page refresh.

This also means that there is no dependency for the viewer part on Cadquery. The viewer only deals with numpy arrays and pythreejs. Only the show function uses Cadquery code. And if jupyter cadquery is deployed to the same env as your cadquery, the versions will fit automatically.

Additionally, I found the issue around voila: I need to create a kernelspec called jcv first and tell voila to use it. Will update the git repo today or tomorrow. Up to then jupyter lab will do the trick

jmwright commented 3 years ago

Ah, ok. It's working now for me. That's mind warping for me to run Python on the command line and have it update in the browser.

Nice work! I think that once you release this integration I'll put a note at the top of the cadquery-gui readme that this is the best replacement for that project since I really only do security updates on it now. I'm assuming this will display assemblies and do animations as well, correct?

bernhard-42 commented 3 years ago

Yes, it can show everything jupyter-cadquery can - except animations for now (see below)

A little more details:

This ensures that whatever I build into jupyter-cadquery will also be available for the viewer. I didn't want to maintain 2 code streams ...

For the time being, there is no message defined to push animation data to the viewer. This is some future feature I will consider in the next release. This release will cover everything except animations.

bernhard-42 commented 3 years ago

Release RC1 of Jupyter-CadQuery, so closing this issue