Skip to content

Commit

Permalink
Merge pull request #1802 from gdsfactory/improve_plot_jupyter
Browse files Browse the repository at this point in the history
Improve plot jupyter
  • Loading branch information
joamatab committed Jun 23, 2023
2 parents b2bc25b + c36e61e commit 29f8bd0
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 48 deletions.
6 changes: 3 additions & 3 deletions gdsfactory/cli.py
Expand Up @@ -165,10 +165,10 @@ def init() -> None:

@click.command()
def notebooks() -> None:
"""Convert notebooks to ipynb."""
from gdsfactory.install import convert_markdown_to_ipynb
"""Convert notebooks in py to ipynb."""
from gdsfactory.install import convert_py_to_ipynb

convert_markdown_to_ipynb()
convert_py_to_ipynb()


# EXTRA
Expand Down
58 changes: 35 additions & 23 deletions gdsfactory/component.py
Expand Up @@ -57,7 +57,8 @@
"widget",
"klayout",
"qt",
] # qt and holoviews
"kweb",
] # qt and holoviews are deprecated
Axis = Literal["x", "y"]


Expand Down Expand Up @@ -1527,9 +1528,9 @@ def plot_klayout(
component.plot(plotter="matplotlib")

def plot_jupyter(self):
"""Shows current gds in klayout. Uses Kweb if server running.
"""Shows current gds in klayout.
if not tries using Klayout widget and finally defaults to matplotlib.
Uses Kweb if installed, otherwise displays Klayout image.
"""
try:
import os
Expand All @@ -1540,33 +1541,42 @@ def plot_jupyter(self):

from gdsfactory.config import PATH
from gdsfactory.pdk import get_layer_views
except ImportError:
print(
"You can install `pip install gdsfactory[cad]` for better visualization"
)
return self.plot_klayout()

gdspath = self.write_gds(gdsdir=PATH.gdslib / "extra", logging=False)

dirpath = GDSDIR_TEMP
dirpath.mkdir(exist_ok=True, parents=True)
lyp_path = dirpath / "layers.lyp"

gdspath = self.write_gds(gdsdir=PATH.gdslib / "extra", logging=False)
layer_props = get_layer_views()
layer_props.to_lyp(filepath=lyp_path)

dirpath = GDSDIR_TEMP
dirpath.mkdir(exist_ok=True, parents=True)
lyp_path = dirpath / "layers.lyp"
port = kj.port if hasattr(kj, "port") and kj.port else 8000
src = f"http://127.0.0.1:{port}/gds?gds_file={escape(str(gdspath))}&layer_props={escape(str(lyp_path))}"

layer_props = get_layer_views()
layer_props.to_lyp(filepath=lyp_path)
os.environ["KWEB_PORT"] = str(os.getenv("KWEB_PORT", port))

port = kj.port if hasattr(kj, "port") else 8000
if not kj.jupyter_server:
port = int(os.getenv("KWEB_PORT"))
while kj.is_port_in_use(port):
port += 1

src = f"http://127.0.0.1:{port}/gds?gds_file={escape(str(gdspath))}&layer_props={escape(str(lyp_path))}"
os.environ["KWEB_PORT"] = str(port)
logger.debug(src)
kj.start()

if kj.jupyter_server and not os.environ.get("DOCS", False):
return IFrame(
src=src,
width=1400,
height=600,
)
else:
return self.plot_klayout()
except ImportError:
print(
"You can install `pip install gdsfactory[full]` for better visualization"
if kj.jupyter_server:
return IFrame(
src=src,
width=1400,
height=600,
)
else:
return self.plot_klayout()

def plot_matplotlib(self, **kwargs) -> None:
Expand Down Expand Up @@ -1598,7 +1608,7 @@ def plot(self, plotter: str | None = None, **kwargs) -> None:
We recommend using klayout.
Args:
plotter: plot backend ('matplotlib', 'widget', 'klayout').
plotter: plot backend ('matplotlib', 'widget', 'klayout', 'kweb').
"""
plotter = plotter or CONF.display_type

Expand All @@ -1608,6 +1618,8 @@ def plot(self, plotter: str | None = None, **kwargs) -> None:
if plotter == "klayout":
self.plot_klayout()
return
elif plotter == "kweb":
return self.plot_jupyter()
elif plotter == "widget":
self.plot_widget()
return
Expand Down
2 changes: 1 addition & 1 deletion gdsfactory/config.py
Expand Up @@ -194,7 +194,7 @@ class Settings(BaseSettings):
n_threads: int = get_number_of_cores()
logger: ClassVar[Logger] = logger
logfilter: LogFilter = Field(default_factory=LogFilter)
display_type: Literal["widget", "klayout", "docs"] = "widget"
display_type: Literal["widget", "klayout", "docs", "kweb"] = "kweb"

def __init__(self, **data: Any):
"""Set log filter and run pydantic."""
Expand Down
14 changes: 6 additions & 8 deletions gdsfactory/install.py
Expand Up @@ -148,20 +148,18 @@ def install_klayout_technology(
)


markdown_files = PATH.notebooks.glob("**/*.md")
py_files = PATH.notebooks.glob("**/*.py")


def convert_markdown_to_ipynb(
markdown_files=markdown_files, output_folder=PATH.cwd / "notebooks"
) -> None:
def convert_py_to_ipynb(files=py_files, output_folder=PATH.cwd / "notebooks") -> None:
"""Convert notebooks from markdown to ipynb."""
import jupytext

output_folder.mkdir(exist_ok=True, parents=True)

for markdown_file in markdown_files:
notebook_file = f"{output_folder}/{markdown_file.stem}.ipynb"
nb = jupytext.read(markdown_file)
for file in files:
notebook_file = f"{output_folder}/{file.stem}.ipynb"
nb = jupytext.read(file)
jupytext.write(nb, notebook_file)


Expand All @@ -173,4 +171,4 @@ def convert_markdown_to_ipynb(
# write_git_attributes()
# install_gdsdiff()
# install_klayout_package()
convert_markdown_to_ipynb()
convert_py_to_ipynb()
8 changes: 4 additions & 4 deletions gdsfactory/plugins/web/server_jupyter.py
Expand Up @@ -8,10 +8,10 @@
jupyter_server = None


def _run() -> None:
def _run(port: int = 8000) -> None:
global jupyter_server

config = uvicorn.Config(app)
config = uvicorn.Config(app, port=port)
jupyter_server = uvicorn.Server(config)
loop = asyncio.get_event_loop()
loop.create_task(jupyter_server.serve())
Expand All @@ -22,7 +22,7 @@ def _server_is_running() -> bool:
return False if jupyter_server is None else jupyter_server.started


def start() -> None:
def start(port: int = 8000) -> None:
"""Start a jupyter_server if it's not already started."""
if not _server_is_running():
_run()
_run(port=port)
34 changes: 27 additions & 7 deletions gdsfactory/samples/notebooks/workflow_jupyter_notebooks.py
@@ -1,32 +1,52 @@
# ---
# jupyter:
# jupytext:
# cell_metadata_filter: -all
# custom_cell_magics: kql
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.11.2
# kernelspec:
# display_name: base
# language: python
# name: python3
# ---

# %% [markdown]
# # Jupyter notebooks
#
# Working with Jupyter notebooks is great for learning gdsfactory as well as running heavy simulations on Cloud servers.
#
# Thanks to [kweb](https://github.com/gdsfactory/kweb) you can use the webapp version on klayout in your browser or inside jupyter notebooks.

# +
import kweb.server_jupyter as kj # requires `pip install gdsfactory[full]` or `pip install kweb`
# %%
import gdsfactory as gf

gf.config.rich_output()
PDK = gf.get_generic_pdk()
PDK.activate()

gf.config.set_log_level("DEBUG")
kj.start()
# -
gf.CONF.display_type = "kweb"

# %%
c = gf.components.mzi()

c.plot_jupyter()
# %%
c.plot()

# %%
c = gf.components.bend_circular()
c.plot_jupyter()

# %%
c = gf.components.straight_heater_meander()
c.plot_jupyter()
c.plot()

# %%
c.plot()

# %%
s = c.to_3d()
s.show()
4 changes: 2 additions & 2 deletions pyproject.toml
Expand Up @@ -69,7 +69,7 @@ cad = [
"ipytree",
"rich-click",
"ipycytoscape",
"kweb>=0.0.11,<0.1",
"kweb==0.1.1",
"jinja2",
"python-multipart",
"fastapi",
Expand Down Expand Up @@ -149,7 +149,7 @@ full = [
"ipytree",
"rich-click",
"ipycytoscape",
"kweb>=0.0.11,<0.2",
"kweb==0.1.1",
"jinja2",
"python-multipart",
"fastapi",
Expand Down

0 comments on commit 29f8bd0

Please sign in to comment.