Postprocessing nettracer

Hi all,

I'd like to do some postprocessing on the trace extracted using the nettracer (e.g. its impedance, total length, ...). Unfortunately, I could not find a way to access the nettracer object from the GUI in the python scripting environment.
To circumvent this issue, I tried to write a plugin in which I used the nettracer class. There are several problems here

  • When the plugin is active, the selection tool no longer works. This is because the plugin captures the mouse clicks, but I'd like to retain the ability to select shapes
  • I am unable to highlight the trace in the scripting environment

The code I have as of know is this (using snippets from the forum here and there)

import pya

class HighlightPluginFactory(pya.PluginFactory):

  def __init__(self):
    super(HighlightPluginFactory, self).__init__()
    pya.MainWindow.instance()  # (workaround for bug 191)
    self.register(1000, "highlight", "Highlight track")

  def create_plugin(self, manager, root, view):
    return HighlightPlugin()
  # Keeps the singleton instance
  instance = None

# Create and store the singleton instance
HighlightPluginFactory.instance = HighlightPluginFactory()

# Second thing is the actual plugin

class HighlightPlugin(pya.Plugin):

  def __init__(self):
    super(HighlightPlugin, self).__init__()

  def activated(self):
    pya.MainWindow.instance().message("Click on trace", 10000)

  def deactivated(self):
    pya.MainWindow.instance().message("", 0)

  def mouse_click_event(self, p, buttons, prio):
    # This is where everything happens
    if prio:
      lv = pya.LayoutView.current()
      ly =

      dbu = ly.dbu

      tracer = pya.NetTracer()

      tech = pya.NetTracerTechnology()
      tech.connection("31/0", "51/0", "32/0")
      tech.connection("32/0", "52/0", "33/0")
      tech.connection("33/0", "53/0", "34/0")
      tech.connection("34/0", "54/0", "35/0")
      tech.connection("35/0", "55/40", "36/40")
      tech.connection("36/40", "56/40", "37/60")

      tracer.trace(tech, ly, ly.top_cell(), pya.Point(p.x/dbu, p.y/dbu), ly.find_layer(34, 0))  # Rather than entering the layer, I'd like to use the layer of the selected shape
      return True
    return False

Subsequently, I'd like to highlight and post-process the extracted trace, but unfortunately, I've been unable to highlight anything.


  • Hi,

    a plugin is a tool option - if the plugin is active, it will take full control over the mouse. Hence you cannot have both select mode and your own tool feature while the plugin is active.

    The net tracer's approach is to grab the mouse and release it once the action is taken. You can achieve this by providing a menu entry and actively calling grab_mouse in the menu event handler. This is a somewhat "temporary" mode and switching of the tool does not happen. This maybe is more acceptable.

    Highlighting can be done by create "Marker" objects. Each marker represents one shape, so you may need a lot of markers. However, you need to implement all the logic of managing the marker's lifetime.

    I'd discourage you from trying to duplicate the whole net tracer functionality. It's a fairly complex tool and not all the functionality you'll need may be available through Python API. Please keep in mind that the Python API is built to extend KLayout, not to duplicate existing features. I also guess that for a decent size of the nets, a Python-based solution will be painfully slow and there are manifold pitfalls because Python employs a very different memory management model than the underlying C++ layer.

    I'd suggest to look into the C++ implementation. You mentioned you don't see how to access the net objects kept inside the tool: I definitely think that adding this API is much easier than duplicating the whole feature.


  • Thanks! I have no intention of rewriting the nettracer functionality, but with what you just told I think it should be doable to accomplish the goal without too much pain.

  • hi Matthias
    I see you mention about grab_mouse. I just used Klayout some days ago. I trying catch mouse event(no need active plugin mode) but I don't know where I should put grab_mouse in my plugin. If you can put a small example to description about how to use it?

    Thank you for you helping!


  • edited May 2019

    Hi dai,

    here is small example how to use the grab_mouse method. It's used when you want to capture the mouse from a menu callback.

    class OnMouseClickPluginFactory(pya.PluginFactory):
      def __init__(self):
        super(OnMouseClickPluginFactory, self).__init__()
        # this tool is only available through menu:
        self.has_tool_entry = False
        self.add_menu_entry("trigger", "trigger", "tools_menu.end", "Demo Plugin Trigger")
        self.register(-1000, "on_click", "On Click")
      def create_plugin(self, manager, root, view):
        return OnMouseClickPlugin()
      # Keeps the singleton instance
      instance = None
    # Create and store the singleton instance
    OnMouseClickPluginFactory.instance = OnMouseClickPluginFactory()
    class OnMouseClickPlugin(pya.Plugin):
      def __init__(self):
        super(OnMouseClickPlugin, self).__init__()
      def menu_activated(self, symbol):
        if symbol == "trigger":
          pya.MainWindow.instance().message("Click on point to set the origin", 10000)
      def mouse_click_event(self, p, buttons, prio):
        # This is where everything happens
        if prio:
          print("Mouse clicked at " + str(p))
          return True
        return False


Sign In or Register to comment.