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

LayoutView.select_all() not working / not selecting anything #1823

Closed
fawqati-spherical opened this issue Aug 5, 2024 · 8 comments · Fixed by #1824
Closed

LayoutView.select_all() not working / not selecting anything #1823

fawqati-spherical opened this issue Aug 5, 2024 · 8 comments · Fixed by #1824
Assignees
Labels
Milestone

Comments

@fawqati-spherical
Copy link

fawqati-spherical commented Aug 5, 2024

Klayout Version = 0.28.12 (also tested on 0.29.4)
Python Version = 3.11.2
Access method = Macro Development IDE

Please see code below. clear_selection() works if i select all objects manually. However, i cant get the select_all() to select anything. Ive tried accessing the LayoutView in 2 different ways but that made no difference.
NB: in fact lv.select_all() seems to clear the selection !

Workaround suggested = mw.cm_select_all()

  • However, note that this method is deprecated in the documentation.
  • Also the number of returned items is NOT EQUAL to the manual selection in KLayout gui !!!

Testcase:

import pya

mw = pya.Application.instance().main_window()
#lv = pya.LayoutView.current()
lv = mw.current_view()

#lv.clear_selection()
lv.select_all()
print(f'selection_size = {lv.selection_size()}')
@klayoutmatthias
Copy link
Collaborator

klayoutmatthias commented Aug 5, 2024

Thanks for this bug report.

The formally correct and non-deprecated way of calling "cm_select_all" is

mw.call_menu("cm_select_all")

But there is no difference between this function and using Edit/Select All. So what do you mean exactly by "Also the number of returned items is NOT EQUAL to the manual selection in KLayout gui !!!"?

In case you refer to the selection count reported by lv.selection_size(): this may be different from the number of selected objects reported by the GUI. The reason is: lv.selection_size() only returns the selected shapes and instances. But there are other selectable objects like rulers or images. So "Select All" may show more objects than lv.selection_size() reports, if there are rulers selected as well.

@fawqati-spherical
Copy link
Author

fawqati-spherical commented Aug 6, 2024

Hi Matthias,

Thanks for your patience with my delayed response, but i wanted to be accurate with the information below:

If i manually select all objects in a layout, then in my current example testcase, at the bottom KLayout footer info bar, i get 183 reported. If i then deselect, and use the APP menu bar's select all or i use the mw.call_menu("cm_select_all") i get LESS and its 144 !

So as a current workaround, I select all objects in a layout manually and then use either lv.object_selection or [i for i in lv.each_object_selected()] and find the list's length.

Please let me know how i might be able to package this up into a self contained test case.

We really appreciate your help.

Faisal

@klayoutmatthias
Copy link
Collaborator

I played around to reproduce your issue and there is one thing that is odd about "cm_select_all": as it basically does a "select" with a box equal to the cell's bounding box, it will not capture such texts:

image

Reason is that the text (including the glyphs) has to be enclosed in the selection box.

When the text is completely inside the cell box, it is selected with "select all" as well:

image

Maybe you can confirm whether this explains your observations. If so, I can try to fix that in this ticket as well.

Thanks,

Matthias

@fawqati-spherical
Copy link
Author

fawqati-spherical commented Aug 8, 2024

Morning Matthias,

Good spot. Its helping me get a better understanding so sincerely appreciated.

I confirm that your observations are certainly a part of the issue im seeing at my side, but i think theres more to it than that. My notes below:

  1. Firstly, the cm_select_all function seems to be a function of the zoom level. Not sure this is expected/intended behaviour, but its certainly selecting subsets of the total manually selectable set.

  2. I might understand if that was intended when zooming 'IN', but in my case, which i had reported at the beginning of this ticket, it seems that the cm_select_all() gives a lower total selected number when zooming 'OUT' !!

My current hypothesis is, yes some text seems to diplay beyond the cell boundary / bbox, but depending on the zoom, if that text is hierarchical in another cell / instance, then it is unaccounted for and thus the total number of selected objects varies dramatically. I am trying to confirm this programmatically (see below) by creating a list of all instances in a layout and then comparing the differences.

Ps.
Matthias, I wonder whether we could help each other out here. This whole task started for me inheriting an IC design with cells randomly having hundreds or upto a million duplicated instances. As you can imagine, this is making DRC/LVS very time consuming yet alone the integrity of the layout dB. But im struggling with how to exactly find each object and get its info such as (type, size, bbox, trans, pcell, shape, etc...)

If we can get a script to report every selected object hierarchically in different scenarios, then i believe it will help us isolate exactly the problem with cm_select_all, but also kill 2 birds and help me with my remove_duplicates() function.

@klayoutmatthias
Copy link
Collaborator

klayoutmatthias commented Aug 8, 2024

Hi @fawqati-spherical,

I imagine that your design got spoiled when someone used multiple Layout#read into the same layout. This function "merges" Layouts - specifically it duplicates instances if you load the same hierarchy tree twice. It has been changed in version 0.29.2 for a less messy behavior, but there may still be old designs around.

You can see that here: use this file

x.gds.zip

and this script:

# merge.py
import klayout.db as kdb

ly = kdb.Layout()

ly.read("x.gds")
ly.read("x.gds")

ly.write("y.gds")

You have to use an old version of the klayout Python package, e.g.

pip3 install klayout==0.28.17.post1
python3 merge.py

The result will be a file called "y.gds" which has 8 instances of the "A" cell instead of one and effectively 16 layer 1 rectangles instead of two.

But there is simple fix for that: just convert to OASIS and back to GDS. The OASIS writer strips duplicates during the OASIS repetition generation step:

# buddy tools from KLayout installation:
strm2oas y.gds y.oas
strm2gds y.oas y_fixed.gds

Matthias

klayoutmatthias pushed a commit that referenced this issue Aug 8, 2024
1. Fixed "LayoutView#select_all"
2. Box selection now will select texts at their origin again:
   this way it is included in the bounding box. Point mode still
   takes the text's glyph area.
@klayoutmatthias klayoutmatthias self-assigned this Aug 8, 2024
@klayoutmatthias klayoutmatthias linked a pull request Aug 8, 2024 that will close this issue
klayoutmatthias added a commit that referenced this issue Aug 10, 2024
Fixed bug #1823 (select_all not working)
@klayoutmatthias
Copy link
Collaborator

Got closed automatically when merging the PR.

@klayoutmatthias klayoutmatthias added this to the 0.29.6 milestone Aug 14, 2024
@fawqati-spherical
Copy link
Author

Servus Matthias,

  1. Thanks for your patience with my radio silence as i was diverted to firefighting a bunch of other issues in our flow.

  2. THANK YOU SO SO MUCH for v0.29.6 !!! I confirm the fixes are working on a number of errors i had applied them to.

  3. I also managed to get your GDS merge solution, but as suspected, this smashes the hierarchy, especially the pcells which i would've like to avoid if possible. In my script, i check the identity, position, bbox, rotation and pcell info if it is one, and then simply remove duplication of objects if they all match.

  4. I have one final question related to this topic please ?

  • Is there a way to select all objects (cells and shapes) from either a Layout class or a Cell Class ?
  • FYI, There would be several advantages programatically if this was possible as apposed to the current select_all() method from the LayoutView Class !
  • Currently a number of methods exist ( for example layout.each_cell() or layout.top_cell().each_inst() ) but these return cells not for shapes.
  • Is there a function from a Layout or Cell Class Objects that would returns all shape objects or both cells+shapes, akin to the LV.select_all() method ?

Thanks again for all your help. I am sincerely in gratitude of your debt.

Faisal

@klayoutmatthias
Copy link
Collaborator

Sorry, but I don't understand what you're trying. Cells and Shapes are fundamentally different objects, so they should not appear on the same level in any reasonable algorithm.

Maybe you look for something like the RecursiveShapeIterator. This iterator delivers shapes, but also allows retrieving the context of the cells. It is called the instantiation path and consists of a series of cell instances leading to a particular shape instance.

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

Successfully merging a pull request may close this issue.

2 participants