Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lay.Marker missing in python standalone module #1655

Closed
sebastian-goeldi opened this issue Mar 13, 2024 · 7 comments · Fixed by #1761
Closed

lay.Marker missing in python standalone module #1655

sebastian-goeldi opened this issue Mar 13, 2024 · 7 comments · Fixed by #1761
Assignees
Milestone

Comments

@sebastian-goeldi
Copy link
Contributor

sebastian-goeldi commented Mar 13, 2024

Hello Matthias,

I hope you are doing well.

I am currently trying to use markers in the python qt-less LayoutView (totally not related to #1632 ;) ). I noticed that in KLayout GUI pya.Marker works like I would expect (to some degree see bottom). In python (or more specifically the rdb view of kweb 2.0) I cannot get marker(s) to show.

I assume there is some backend magic which is disabled (or straight up missing because it's part of the gui) for the python binding?

Best,
Sebastian

P.S. is it possible to make multiple markers show up at the same time? My uneducated guess is the marker is a singleton in C++ (per LayoutView) and thererfore they erase each other, but the marker browser can do it, so I assume there is at least a possibility to do so.

@klayoutmatthias
Copy link
Collaborator

Hi Sebastian,

Markers are not singletons - you can add as many markers as you like. Display gets kind of sluggish when you have 1 million markers or so, but a thousand should not be an issue.

I need to debug why markers don't show with standalong LayoutView. Maybe a similar issue than what we had in the past. The standalone view is special because there is no event loop running in the background and some essential update events may not happen.

Thanks for reporting this issue,

Matthias

@sebastian-goeldi
Copy link
Contributor Author

Thanks Matthias!

I am pretty sure the marker class behaves kind of singleton-ish even in the macroeditor in klayout. I will update it later today.

I think I won't need 1 million markers ;). I was planning to hard-limit it to a default of 100 anyway, since I need to serialize and deserialize the markers (and RdbItems) and send them through the websocket.

@klayoutmatthias klayoutmatthias added this to the 0.29 milestone Mar 21, 2024
@klayoutmatthias
Copy link
Collaborator

I think I get some understanding what is going on.

First, the functionality of the marker seems to be okay in the standalone module.

This code works:

from klayout.db import DBox, DPoint
from klayout.lay import LayoutView, Annotation, Marker

lv = LayoutView()
lv.load_layout("./testdata/lvs/resistor.gds")
lv.max_hier()

marker = Marker(lv)
marker.set(DBox(6.0, 0.0, 8.0, 2.0))

lv.get_pixels(600, 600).write_png("test.png")

which produces this image:

test

However, this code does not produce two markers, but only one:

from klayout.db import DBox, DPoint
from klayout.lay import LayoutView, Annotation, Marker

lv = LayoutView()
lv.load_layout("./testdata/lvs/resistor.gds")
lv.max_hier()

marker = Marker(lv)
marker.set(DBox(6.0, 0.0, 8.0, 2.0))

marker = Marker(lv)
marker.set(DBox(9.0, 0.0, 11.0, 2.0))

lv.get_pixels(600, 600).write_png("test.png")

test

The reason is that marker appearance is tied to the object lifetime. When the second object is created, it will replace the first one as they use the same variable. Because of this, the first object is deleted and vanishes.

For the same reason, this code does not produce any marker at all:

from klayout.db import DBox, DPoint
from klayout.lay import LayoutView, Annotation, Marker

lv = LayoutView()
lv.load_layout("./testdata/lvs/resistor.gds")
lv.max_hier()

def make_marker(lv):
  marker = Marker(lv)
  marker.set(DBox(6.0, 0.0, 8.0, 2.0))

make_marker(lv)
lv.get_pixels(600, 600).write_png("test.png")

Here the reason is scope: when the "make_marker" function returns, the marker object stored inside the "marker" variable is destroyed and the marker vanishes.

To solve the issue, a reference to the markers need to be kept. A way to doing that is to attach them to the view:

from klayout.db import DBox, DPoint
from klayout.lay import LayoutView, Annotation, Marker

lv = LayoutView()
lv.load_layout("./testdata/lvs/resistor.gds")
lv.max_hier()

lv.markers = []

marker = Marker(lv)
marker.set(DBox(6.0, 0.0, 8.0, 2.0))
lv.markers.append(marker)

marker = Marker(lv)
marker.set(DBox(9.0, 0.0, 11.0, 2.0))
lv.markers.append(marker)

lv.get_pixels(600, 600).write_png("test.png")

And here are the two markers :)

test

I can basically change the lifetime management for the markers and transfer ownership to the layout view. I just wonder whether that would break existing code.

Matthias

@sebastian-goeldi
Copy link
Contributor Author

Thanks Matthias! I will use this. Whether to attach it to the LayoutView; I would suggest to do so (I would have expected it to behave similar to a Shapes container but on um (grid) and therefore there also being a clear_makers() or similar. But maybe that doesn't make sense from an architecture point of view. But I can also live with the current implementation. Important to know that the objects can be garbage collected and then "vanish", but workable.

@klayoutmatthias
Copy link
Collaborator

Yes, I admit that is kind of freaky, but it has been like this for long now.

I could provide an alternative path of creating markers and adding them to the view, thus transferring ownership. Maybe that is easier to work with than to manage the ownership separately.

@klayoutmatthias klayoutmatthias modified the milestones: 0.29, 0.29.1 Mar 28, 2024
@klayoutmatthias klayoutmatthias modified the milestones: 0.29.1, 0.29.2 Apr 29, 2024
@klayoutmatthias klayoutmatthias modified the milestones: 0.29.2, 0.29.3 Jun 8, 2024
@klayoutmatthias klayoutmatthias self-assigned this Jun 29, 2024
@klayoutmatthias klayoutmatthias linked a pull request Jun 29, 2024 that will close this issue
@klayoutmatthias
Copy link
Collaborator

klayoutmatthias commented Jun 30, 2024

I provided the following alternative way for Marker lifetime management:

lv = ... # some LayoutView
m = pya.Marker()   # without view argument!
lv.add_marker(m)   # now owned by the view - the variable can go out of scope now.

# to delete:
lv.clear_markers()
# or:
m._destroy()

Matthias

@sebastian-goeldi
Copy link
Contributor Author

Thank you Matthias!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants