KLayout/klayout

LayoutView.select_all() not working / not selecting anything

Closed this issue · 8 comments

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()}')

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.

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

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

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.

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

Got closed automatically when merging the PR.

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

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.