From 26f1806e73e45272989adc7f1e9cc830c6883083 Mon Sep 17 00:00:00 2001 From: Lukas Chrostowski Date: Thu, 14 Nov 2024 00:04:35 -0800 Subject: [PATCH] extend pya.Cell().image export a PNG image of the cell layout v0.5.17 --- klayout_dot_config/grain.xml | 2 +- klayout_dot_config/python/SiEPIC/__init__.py | 2 +- klayout_dot_config/python/SiEPIC/extend.py | 140 +++++++++++------- klayout_dot_config/python/pyproject.toml | 2 +- .../EBeam_LukasChrostowski_MZI2_FaML.gds | Bin 0 -> 8386 bytes .../tech/GSiP/pymacros/tests/test_FaML.py | 7 + 6 files changed, 97 insertions(+), 56 deletions(-) create mode 100644 klayout_dot_config/tech/GSiP/pymacros/tests/EBeam_LukasChrostowski_MZI2_FaML.gds diff --git a/klayout_dot_config/grain.xml b/klayout_dot_config/grain.xml index e19adfc8..8e8645c2 100644 --- a/klayout_dot_config/grain.xml +++ b/klayout_dot_config/grain.xml @@ -1,7 +1,7 @@ siepic_tools - 0.5.16 + 0.5.17 0.27 SiEPIC Tools Tools for designing Silicon Photonic Integrated Circuits, including waveguides, component simulations, functional verification, DRC verification, Functional verification, netlist extraction, circuit simulations. Layout can be implemented graphically or by programming in Python using the SiEPIC functions and KLayout Python API. Framework and examples for creating layouts using scripts. Includes a generic PDK (GSiP). Other PDKs are installed separately, and depend on SiEPIC-Tools. diff --git a/klayout_dot_config/python/SiEPIC/__init__.py b/klayout_dot_config/python/SiEPIC/__init__.py index ac7f953c..9dc719ea 100644 --- a/klayout_dot_config/python/SiEPIC/__init__.py +++ b/klayout_dot_config/python/SiEPIC/__init__.py @@ -2,7 +2,7 @@ SiEPIC-Tools package for KLayout ''' -__version__ = "0.5.16" +__version__ = "0.5.17" print("KLayout SiEPIC-Tools version %s" %__version__) diff --git a/klayout_dot_config/python/SiEPIC/extend.py b/klayout_dot_config/python/SiEPIC/extend.py index 7c2cfa93..89e141de 100644 --- a/klayout_dot_config/python/SiEPIC/extend.py +++ b/klayout_dot_config/python/SiEPIC/extend.py @@ -1753,69 +1753,102 @@ def pinPoint(self, pin_name, verbose=False): return matched_pins[0].center -def show(self): - '''Show the cell in KLayout using klive''' +def show(self, file_path = None, lyrdb_filename=None): + ''' + Show the cell in KLayout using klive + + args + file_path: os.path folder location to save + ''' - # Save the cell in a temporary file - from ._globals import TEMP_FOLDER import os - file_out = os.path.join(TEMP_FOLDER, self.name+'.gds') + + if not file_path: + # Save the cell in a temporary file + from ._globals import TEMP_FOLDER + file_path = TEMP_FOLDER + + file_out = os.path.join(file_path, self.name+'.gds') self.write(file_out) # Display in KLayout from SiEPIC._globals import Python_Env if Python_Env == 'Script': from SiEPIC.utils import klive - klive.show(file_out, technology=self.layout().technology().name, keep_position=True) + klive.show(file_out, lyrdb_filename=lyrdb_filename, technology=self.layout().technology().name, keep_position=True) + def plot(self, width = 800, show_labels = True, show_ruler = True, retina = True): - ''' - Generate an image of the layout cell, and display. Useful for Jupyter notebooks - - Args: - self: pya.Cell - width: number of pixels - show_labels: KLayout display config to show text = True, https://www.klayout.de/doc-qt5/code/class_LayoutView.html#method101 - show_ruler: KLayout display config to show ruler = True - retina: IPython.display.Image configuration for retina display, True - ''' - - from io import BytesIO - from IPython.display import Image, display - - # Create a LayoutView, and populate it with the current cell & layout - cell = self - layout_view = pya.LayoutView() - cell_view_index = layout_view.create_layout(True) - layout_view.active_cellview_index = cell_view_index - cell_view = layout_view.cellview(cell_view_index) - layout = cell_view.layout() - layout.assign(cell.layout()) - cell_view.cell = layout.cell(cell.name) - - # Load layer properties from the technology - lyp_path=layout.technology().eff_layer_properties_file() - if not lyp_path: - raise Exception ('SiEPIC.extend.plot: technology not specified.') - layout_view.load_layer_props(lyp_path) - - # Configure the layout view settings - # print(layout_view.get_config_names()) - layout_view.set_config("text-font",3) - layout_view.set_config("background-color", "#ffffff") - layout_view.set_config("text-visible", "true" if show_labels else "false") - layout_view.set_config("grid-show-ruler", "true" if show_ruler else "false") - - # Zoom out and show all layout details - layout_view.max_hier() - layout_view.zoom_fit() - - # Display as a PNG - width = width * (2 if retina else 1) - pixel_buffer = layout_view.get_pixels(width, cell.bbox().height()/cell.bbox().width()*width) - png_data = pixel_buffer.to_png_data() - im = Image(png_data, retina=retina) - display(im) + ''' + Generate an image of the layout cell, and display. Useful for Jupyter notebooks + + Args: + self: pya.Cell + width: number of pixels + show_labels: KLayout display config to show text = True, https://www.klayout.de/doc-qt5/code/class_LayoutView.html#method101 + show_ruler: KLayout display config to show ruler = True + retina: IPython.display.Image configuration for retina display, True + ''' + + from io import BytesIO + from IPython.display import Image, display + + # Create a LayoutView, and populate it with the current cell & layout + cell = self + layout_view = pya.LayoutView() + cell_view_index = layout_view.create_layout(True) + layout_view.active_cellview_index = cell_view_index + cell_view = layout_view.cellview(cell_view_index) + layout = cell_view.layout() + layout.assign(cell.layout()) + cell_view.cell = layout.cell(cell.name) + + # Load layer properties from the technology + lyp_path=layout.technology().eff_layer_properties_file() + if not lyp_path: + raise Exception ('SiEPIC.extend.plot: technology not specified.') + layout_view.load_layer_props(lyp_path) + + # Configure the layout view settings + # print(layout_view.get_config_names()) + layout_view.set_config("text-font",3) + layout_view.set_config("background-color", "#ffffff") + layout_view.set_config("text-visible", "true" if show_labels else "false") + layout_view.set_config("grid-show-ruler", "true" if show_ruler else "false") + + # Zoom out and show all layout details + layout_view.max_hier() + layout_view.zoom_fit() + + # Display as a PNG + width = width * (2 if retina else 1) + pixel_buffer = layout_view.get_pixels(width, cell.bbox().height()/cell.bbox().width()*width) + png_data = pixel_buffer.to_png_data() + im = Image(png_data, retina=retina) + display(im) + return im + + +def image(self, file_out = None, file_format = 'PNG', width = 800, show_labels = True, show_ruler = True, retina = True): + ''' + Generate an image of the layout cell, and save + + Args: + self: pya.Cell + file_out: os.path to save the image + file_format: 'PNG' + width: number of pixels + show_labels: KLayout display config to show text = True, https://www.klayout.de/doc-qt5/code/class_LayoutView.html#method101 + show_ruler: KLayout display config to show ruler = True + retina: IPython.display.Image configuration for retina display, True + ''' + + # Create an image of the layout + im = self.plot(width=width, show_labels=show_labels, show_ruler=show_ruler, retina=retina) + # save + with open(file_out, "wb") as f: + f.write(im.data) + ################################################################################# @@ -1831,6 +1864,7 @@ def plot(self, width = 800, show_labels = True, show_ruler = True, retina = True pya.Cell.pinPoint = pinPoint pya.Cell.show = show pya.Cell.plot = plot +pya.Cell.image = image ################################################################################# diff --git a/klayout_dot_config/python/pyproject.toml b/klayout_dot_config/python/pyproject.toml index e24bd321..a91d7fc1 100644 --- a/klayout_dot_config/python/pyproject.toml +++ b/klayout_dot_config/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "SiEPIC" -version = "0.5.16" +version = "0.5.17" authors = [ { name="Lukas Chrostowski", email="lukasc@ece.ubc.ca" }, ] diff --git a/klayout_dot_config/tech/GSiP/pymacros/tests/EBeam_LukasChrostowski_MZI2_FaML.gds b/klayout_dot_config/tech/GSiP/pymacros/tests/EBeam_LukasChrostowski_MZI2_FaML.gds new file mode 100644 index 0000000000000000000000000000000000000000..a6944c1ac116da6ff8418e9fdff7a6f19da4919c GIT binary patch literal 8386 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 0: