Example #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
Example #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
Example #3
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
Example #4
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
Example #5
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())
Example #6
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
Example #7
0
    def output_all(self,
                   output_layers=None,
                   script_globals=None,
                   new_target_layout=True,
                   step_name=None,
                   save_png=None,
                   *args):
        """Output a list of material objects to the output layout

        A list of materials is passed through an output_layers dictionary.

        Parameters
        ----------
        output_layers :  Dict[LayoutData, str] or Dict[str, str]
            Key is either LayoutData instance, or a name of such instance
            instance in script_globals.
            Value is the layer specification (see layer_spec in output()).
        script_globals : Dict[str, Any]
            globals() dictionary
        new_target_layout : bool
            if True, a new target layout will be created
        step_name : str
            name extension for the newly created layout
        save_png : bool
            if True, the resulting view will be saved as an image in the
            gds file folder
        """
        if script_globals is None:
            script_globals = {}

        if new_target_layout:
            if self._is_target_layout_created:
                self._finalize_view()
            self._create_new_layout(cell_name_extension=step_name)

        if output_layers:
            ol = output_layers
        elif self._output_all_parameters['output_layers']:
            ol = self._output_all_parameters['output_layers']
        else:
            return None

        for ld, ls in ol.items():
            if isinstance(ld, str):
                if ld == 'air':
                    a = self.air()
                    self.output(layer_spec=ls, layer_data=a)
                # elif ld in list(globals.keys()):
                #     print('yes', ld, 'in globals')
                #     self.output(layer_spec=ls,
                #                 layer_data=globals[ld])
                elif ld in list(script_globals.keys()):
                    self.output(layer_spec=ls, layer_data=script_globals[ld])
                else:
                    # skip a non-existing (yet) material
                    continue
            else:
                self.output(layer_spec=ls, layer_data=ld)

        if save_png is not None:
            sp = save_png
        else:
            sp = self._output_all_parameters['save_png']

        if sp:
            self._finalize_view()
            if step_name:
                file_name = '{} ({}).png'.format(self._cell_file_name,
                                                 step_name)
            else:
                file_name = '{}.png'.format(self._cell_file_name)

            if self._output_all_parameters['png_path']:
                file_name = os.path.join(
                    self._output_all_parameters['png_path'], file_name)
            else:
                file_name = os.path.join(self._file_path, file_name)

            try:
                self._target_view.save_image(
                    file_name,
                    self._area.width() / 100,
                    self._area.height() / 100,
                )
            except Exception as e:
                if not self._hide_png_save_error:
                    MessageBox.critical(
                        "Error",
                        "Error saving png file {}. \n\n Error: {}. \n\n"
                        "Further error messages will not be displayed.".format(
                            file_name, e),
                        MessageBox.b_ok(),
                    )
                    self._hide_png_save_error = True
        return None