예제 #1
0
    def run_script(self, filename, p1=None, p2=None):
        """ Run .pyxs script

        filename : str
            path to the .pyxs script
        """
        view = Application.instance().main_window().current_view()
        if not view:
            raise UserWarning("No view open for running the pyxs script")

        if p1 is None or p2 is None:
            app = Application.instance()
            scr_view = app.main_window().current_view()  # type: LayoutView
            scr_view_idx = app.main_window().current_view_index
            if not scr_view:
                MessageBox.critical(
                    "Error",
                    "No view open for creating the cross-"
                    "section from",
                    MessageBox.b_ok(),
                )
                return False

            rulers = []

            for a in scr_view.each_annotation():
                rulers.append(a)

            if len(rulers) == 0:
                MessageBox.critical(
                    "Error",
                    "No ruler present for the cross "
                    "section line",
                    MessageBox.b_ok(),
                )
                return None

            p1_arr, p2_arr, ruler_text_arr = [], [], []

            for ruler in rulers:
                p1_arr.append(ruler.p1)
                p2_arr.append(ruler.p2)
                ruler_text_arr.append(ruler.text().split('.')[0])

        else:
            p1_arr, p2_arr, ruler_text_arr = [p1], [p2], ['']
            scr_view_idx = None

        target_views = []
        for p1_, p2_, text_ in zip(p1_arr, p2_arr, ruler_text_arr):

            if scr_view_idx:
                # return to the original view to run it again
                app.main_window().select_view(scr_view_idx)

            view = XSectionGenerator(filename).run(p1_, p2_, text_)
            target_views.append(view)

        return target_views
예제 #2
0
    def run(self, p1, p2, ruler_text=None):
        """

        Parameters
        ----------
        ruler_text : str
            identifier to be used to name a new cross-section cell

        Returns
        -------
        LayoutView
        """
        self._target_view = None
        self._target_cell_name = "PYXS: " + ruler_text if ruler_text else "XSECTION"
        self._cell_file_name = "PYXS_" + ruler_text if ruler_text else "XSECTION"

        self._setup(p1, p2)

        self._update_basic_regions()

        text = None
        try:
            with open(self._file_name, 'r') as file:
                text = file.read()
        except Exception as e:
            MessageBox.critical("Error",
                                "Error reading file {}. \n\nError: {}"
                                .format(self._file_name, e),
                                MessageBox.b_ok())
            return None

        if text is None:
            MessageBox.critical("Error",
                                "Error reading file {}."
                                .format(self._file_name),
                                MessageBox.b_ok())
            return None

        # prepare variables to be visible in the script
        locals_ = dir(self)
        locals_dict = {}
        for attr in locals_:
            if attr[0] != '_':
                locals_dict.update({attr: getattr(self, attr)})

        try:
            exec(text, locals_dict)
        except Exception as e:
            # For development
            # print(e.__traceback__.)
            # print(dir(e))
            MessageBox.critical("Error", str(e), MessageBox.b_ok())
            # pass
            return None

        Application.instance().main_window().cm_lv_add_missing()  # @@@
        self._finalize_view()
        return self._target_view
예제 #3
0
    def run(self):
        """ The basic generation method
        """

        if not self._setup():
            return None

        self._update_basic_regions()

        text = None
        with open(self._file_path) as file:
            text = file.read()

        if not text:
            MessageBox.critical("Error",
                                "Error reading file #{self._file_path}",
                                MessageBox.b_ok())
            return None

        # prepare variables to be visible in the script
        locals_ = dir(self)
        locals_dict = {}
        for attr in locals_:
            if attr[0] != '_':
                locals_dict.update({attr: getattr(self, attr)})

        try:
            exec(text, locals_dict)
        except Exception as e:
            # For development
            # print(e.__traceback__.)
            # print(dir(e))
            MessageBox.critical("Error", str(e), MessageBox.b_ok())
            # pass
            return None

        Application.instance().main_window().cm_lv_add_missing()  # @@@
        if self._lyp_file:
            self._target_view.load_layer_props(self._lyp_file)
        self._target_view.zoom_fit()
        self._target_layout.write(self._target_gds_file_name)

        info('    len(bulk.data) = {}'.format(len(self._bulk.data)))
        self._tech_str = '# This file was generated automatically by pyxs.\n\n'\
                         + layer_to_tech_str(255, self._bulk.data[0],
                                             'Substrate') + self._tech_str
        with open(self._target_tech_file_name, 'w') as f:
            f.write(self._tech_str)

        return None
예제 #4
0
        def _on_triggered_callback():
            """ Load pyxs script menu action.

            Load new .pyxs file and run it.
            """
            view = Application.instance().main_window().current_view()
            if not view:
                MessageBox.critical(
                    "Error",
                    "No view open for creating the cross-"
                    "section from",
                    MessageBox.b_ok(),
                )
                return None

            filename = FileDialog.get_open_file_name(
                "Select cross-section script",
                "",
                "XSection Scripts (*.pyxs);;All Files (*)",
            )

            # run the script and save it
            if filename.has_value():
                self.run_script(filename.value())
                self.make_mru(filename.value())
예제 #5
0
    def _setup(self, p1, p2):
        """
        Parameters
        ----------
        p1 : Point
            first point of the ruler
        p2 : Point
            second point of the ruler

        """
        # locate the layout
        app = Application.instance()
        view = app.main_window().current_view()  # LayoutView
        if not view:
            MessageBox.critical(
                "Error",
                "No view open for creating the cross-"
                "section from",
                MessageBox.b_ok(),
            )
            return False

        cv = view.cellview(view.active_cellview_index())  # CellView
        if not cv.is_valid():
            MessageBox.critical("Error", "The selected layout is not valid",
                                MessageBox.b_ok())
            return False

        self._cv = cv  # CellView
        self._layout = cv.layout()  # Layout
        self._dbu = self._layout.dbu
        self._cell = cv.cell_index  # int

        # get the start and end points in database units and micron
        p1_dbu = Point.from_dpoint(p1 * (1.0 / self._dbu))
        p2_dbu = Point.from_dpoint(p2 * (1.0 / self._dbu))
        self._line_dbu = Edge(p1_dbu, p2_dbu)  # Edge describing the ruler

        # initialize height and depth
        self._extend = int_floor(2.0 / self._dbu + 0.5)  # 2 um in dbu
        self._delta = 10
        self._height = int_floor(2.0 / self._dbu + 0.5)  # 2 um in dbu
        self._depth = int_floor(2.0 / self._dbu + 0.5)  # 2 um in dbu
        self._below = int_floor(2.0 / self._dbu + 0.5)  # 2 um in dbu

        info('    XSG._dbu is:    {}'.format(self._dbu))
        info('    XSG._extend is: {}'.format(self._extend))
        info('    XSG._delta is:  {}'.format(self._delta))
        info('    XSG._height is: {}'.format(self._height))
        info('    XSG._depth is:  {}'.format(self._depth))
        info('    XSG._below is:  {}'.format(self._below))

        return True
예제 #6
0
    def run_script(self, filename):
        """ Run .pyxs script

        filename : str
            path to the .pyxs script
        """
        view = Application.instance().main_window().current_view()
        if not view:
            raise UserWarning("No view open for running the pyxs script")

        # cv = view.cellview(view.active_cellview_index())

        XSectionGenerator(filename).run()
예제 #7
0
        def _on_triggered_callback():
            """ Load pyxs script menu action.

            Load new .pyxs file and run it.
            """
            view = Application.instance().main_window().current_view()
            if not view:
                raise UserWarning("No view open for running the pyxs script")

            filename = FileDialog.get_open_file_name(
                "Select cross-section script", "",
                "XSection Scripts (*.pyxs);;All Files (*)")

            # run the script and save it
            if filename.has_value():
                self.run_script(filename.value())
                self.make_mru(filename.value())
예제 #8
0
    def _create_new_layout(self, cell_name_extension=None):
        if cell_name_extension:
            cell_name = '{} ({})'.format(self._target_cell_name,
                                         cell_name_extension)
        else:
            cell_name = self._target_cell_name

        # create a new layout for the output
        app = Application.instance()
        main_window = app.main_window()
        cv = main_window.create_layout(1)  # type: CellView
        cell = cv.layout().add_cell(cell_name)  # type: Cell
        self._target_view = main_window.current_view()  # type: LayoutView
        self._target_view.select_cell(cell, 0)
        self._target_layout = cv.layout()  # type: Layout
        self._target_layout.dbu = self._dbu
        self._target_cell = cell  # type: cell

        self._is_target_layout_created = True
예제 #9
0
    def __init__(self):
        app = Application.instance()
        mw = app.main_window()

        def _on_triggered_callback():
            """ Load pyxs script menu action.

            Load new .pyxs file and run it.
            """
            view = Application.instance().main_window().current_view()
            if not view:
                raise UserWarning("No view open for running the pyxs script")

            filename = FileDialog.get_open_file_name(
                "Select cross-section script", "",
                "XSection Scripts (*.pyxs);;All Files (*)")

            # run the script and save it
            if filename.has_value():
                self.run_script(filename.value())
                self.make_mru(filename.value())

        def _XSectionMRUAction_callback(script):
            """ *.pyxs menu action

            Load selected .pyxs file and run it.

            Parameters
            ----------
            script : str
            """
            self.run_script(script)
            self.make_mru(script)

        # Create pyxs submenu in Tools
        menu = mw.menu()
        if not menu.is_valid("tools_menu.pyxs3D_script_group"):
            menu.insert_separator("tools_menu.end", "pyxs3D_script_group")
            menu.insert_menu("tools_menu.end", "pyxs3D_script_submenu",
                             "pyxs3D")

        # Create Load XSectionpy Script item in XSection (py)
        global pyxs_script_load_menuhandler
        pyxs_script_load_menuhandler = MenuHandler("Load pyxs script",
                                                   _on_triggered_callback)
        menu.insert_item("tools_menu.pyxs3D_script_submenu.end",
                         "pyxs3D_script_load", pyxs_script_load_menuhandler)
        menu.insert_separator("tools_menu.pyxs3D_script_submenu.end.end",
                              "pyxs3D_script_mru_group")

        # Create list of existing pyxs scripts item in pyxs
        self._mru_actions = []
        for i in range(N_PYXS_SCRIPTS_MAX):
            a = XSectionMRUAction(_XSectionMRUAction_callback)
            self._mru_actions.append(a)
            menu.insert_item("tools_menu.pyxs3D_script_submenu.end",
                             "pyxs3D_script_mru{}".format(i), a)
            a.script = None

        # try to save the MRU list to $HOME/.klayout-processing-mru
        i = 0
        home = os.getenv("HOME", None) or os.getenv("HOMESHARE", None)
        global pyxs_scripts
        if pyxs_scripts:
            for i, script in enumerate(pyxs_scripts.split(":")):
                if i < len(self._mru_actions):
                    self._mru_actions[i].script = script
        elif home:
            fn = home + "\\.klayout-pyxs-scripts"
            try:
                with open(fn, "r") as file:
                    for line in file.readlines():
                        match = re.match('<mru>(.*)<\/mru>', line)
                        if match:
                            if i < len(self._mru_actions):
                                self._mru_actions[i].script = match.group(1)
                            i += 1
            except:
                pass
예제 #10
0
    def _setup(self):

        # locate the layout
        app = Application.instance()
        view = app.main_window().current_view()  # LayoutView
        if not view:
            MessageBox.critical(
                "Error", "No view open for creating the cross "
                "section from", MessageBox.b_ok())
            return False

        # locate the (single) ruler
        rulers = []
        n_rulers = 0
        for a in view.each_annotation():
            # Use only rulers with "plain line" style
            # print(a.style)
            # print(Annotation.StyleLine)
            # if a.style == Annotation.StyleLine:
            rulers.append(a)
            n_rulers += 1

        # if n_rulers == 0 or n_rulers >= 2:
        #     MessageBox.info("No rulers",
        #                         "Number of rulers is not equal to one. "
        #                         "Will be exporting the whole layout",
        #                         pya.MessageBox.b_ok())

        # if n_rulers == 1:
        #     MessageBox.info(
        #             "Box export", "One ruler is present for the cross "
        #             "section line. Will be exporting only shapes in the box",
        #             pya.MessageBox.b_ok())

        cv = view.cellview(view.active_cellview_index())  # CellView
        if not cv.is_valid():
            MessageBox.critical("Error", "The selected layout is not valid",
                                MessageBox.b_ok())
            return False

        self._cv = cv  # CellView
        self._layout = cv.layout()  # Layout
        self._dbu = self._layout.dbu
        self._cell = cv.cell_index  # int

        if n_rulers == 1:
            # get the start and end points in database units and micron
            p1_dbu = Point.from_dpoint(rulers[0].p1 * (1.0 / self._dbu))
            p2_dbu = Point.from_dpoint(rulers[0].p2 * (1.0 / self._dbu))
            self._box_dbu = Box(p1_dbu, p2_dbu)  # box describing the ruler
        else:
            # TODO: choose current cell, not top cell
            top_cell = self._layout.top_cell()
            p1_dbu = (top_cell.bbox().p1 * (1.0 / self._dbu)).dup()
            p1_dbu = top_cell.bbox().p1.dup()
            p2_dbu = (top_cell.bbox().p2 * (1.0 / self._dbu)).dup()
            p2_dbu = top_cell.bbox().p2.dup()
            self._box_dbu = Box(p1_dbu, p2_dbu)  # box describing the top cell

        info('XSG._box_dbu to be used is: {}'.format(self._box_dbu))

        # create a new layout for the output
        cv = app.main_window().create_layout(1)
        cell = cv.layout().add_cell("XSECTION")
        self._target_view = app.main_window().current_view()
        self._target_view.select_cell(cell, 0)
        self._target_layout = cv.layout()
        self._target_layout.dbu = self._dbu
        self._target_cell = cell

        # initialize height and depth
        self._extend = int_floor(2.0 / self._dbu + 0.5)  # 2 um in dbu
        self._delta = 10
        self._height = int_floor(2.0 / self._dbu + 0.5)  # 2 um in dbu
        self._depth = int_floor(2.0 / self._dbu + 0.5)  # 2 um in dbu
        self._below = int_floor(2.0 / self._dbu + 0.5)  # 2 um in dbu

        info('    XSG._dbu is:    {}'.format(self._dbu))
        info('    XSG._extend is: {}'.format(self._extend))
        info('    XSG._delta is:  {}'.format(self._delta))
        info('    XSG._height is: {}'.format(self._height))
        info('    XSG._depth is:  {}'.format(self._depth))
        info('    XSG._below is:  {}'.format(self._below))

        return True
예제 #11
0
    def __init__(self, menu_name='pyxs'):
        self._menu_name = menu_name

        app = Application.instance()
        mw = app.main_window()
        if mw is None:
            print('none')
            return

        def _on_triggered_callback():
            """ Load pyxs script menu action.

            Load new .pyxs file and run it.
            """
            view = Application.instance().main_window().current_view()
            if not view:
                MessageBox.critical(
                    "Error",
                    "No view open for creating the cross-"
                    "section from",
                    MessageBox.b_ok(),
                )
                return None

            filename = FileDialog.get_open_file_name(
                "Select cross-section script",
                "",
                "XSection Scripts (*.pyxs);;All Files (*)",
            )

            # run the script and save it
            if filename.has_value():
                self.run_script(filename.value())
                self.make_mru(filename.value())

        def _XSectionMRUAction_callback(script):
            """ *.pyxs menu action

            Load selected .pyxs file and run it.

            Parameters
            ----------
            script : str
            """
            self.run_script(script)
            self.make_mru(script)

        # Create pyxs submenu in Tools
        menu = mw.menu()

        if not menu.is_valid("tools_menu.{}_script_group".format(
                self._menu_name)):
            menu.insert_separator("tools_menu.end",
                                  "{}_script_group".format(self._menu_name))
            menu.insert_menu(
                "tools_menu.end",
                "{}_script_submenu".format(self._menu_name),
                self._menu_name,
            )

        # Create Load XSection.py Script item in XSection (py)
        # global pyxs_script_load_menuhandler
        self.pyxs_script_load_menuhandler = MenuHandler(
            "Load pyxs script", _on_triggered_callback)
        menu.insert_item(
            "tools_menu.{}_script_submenu.end".format(self._menu_name),
            "{}_script_load".format(self._menu_name),
            self.pyxs_script_load_menuhandler,
        )
        menu.insert_separator(
            "tools_menu.{}_script_submenu.end.end".format(self._menu_name),
            "{}_script_mru_group".format(self._menu_name),
        )

        # Create list of existing pyxs scripts item in pyxs
        self._mru_actions = []
        for i in range(N_PYXS_SCRIPTS_MAX):
            a = XSectionMRUAction(_XSectionMRUAction_callback)
            self._mru_actions.append(a)
            menu.insert_item(
                "tools_menu.{}_script_submenu.end".format(self._menu_name),
                "{}_script_mru{}".format(self._menu_name, i),
                a,
            )
            a.script = None

        # try to save the MRU list to $HOME/.klayout-pyxs-scripts
        i = 0
        home = os.getenv("HOME", None) or os.getenv("HOMESHARE", None)
        global pyxs_scripts
        if pyxs_scripts:
            for i, script in enumerate(pyxs_scripts.split(":")):
                if i < len(self._mru_actions):
                    self._mru_actions[i].script = script
        elif home:
            fn = os.path.join(home, '.klayout-pyxs-scripts')
            try:
                with open(fn, "r") as file:
                    for line in file.readlines():
                        match = re.match('<mru>(.*)<\/mru>', line)
                        if match:
                            if i < len(self._mru_actions):
                                self._mru_actions[i].script = match.group(1)
                            i += 1
            except:
                pass