Behavior of Region object when source is modified

edited October 9 in Python scripting

Hello,
I create a Region r with an iterator, and I later delete an instance that participated to create that Region.
Surprisingly, I observe that r is modified, even though if I didn't operate on it:

  • The Region became empty (see the debug file).
  • The area of the Region is non-zero even though it is empty (it remained to the value before the region vanished).

Can you explain this behavior? Where is it documented? Is the Region holding data itself or is it a view in the memory of the database?
Olivier

import pya

mw = pya.MainWindow.instance()      # MainWindow
lv = pya.LayoutView.current()       # LayoutView
cv = lv.active_cellview()           # CellView
layout = cv.layout()                # Layout

cell = layout.cell("TOP")           # Cells
hole = layout.cell("Hole")

iter = cell.begin_shapes_rec(layout.find_layer(2,0))
iter.maxdepth = 0
r = pya.Region(iter)                # Create Region 'r'

print("(1) Area: ", r.area())

for inst in cell.each_inst():       # Delete a cell instance
  if inst.cell.name == "Hole":
    inst.delete()   

print("(2) Area: ", r.area())       # Check Region 'r'
r.write("debug.gds")

# Setup the display
lv.reload_layout(cv.index())            # Reload original file
mw.load_layout("debug.gds", mode=1)     # Display the debug file

Comments

  • edited October 10

    Hi @ocasta,

    I asked ChatGPT and it confirmed that original layer regions maintain their relationship with the original layout :)

    My advice is to stay away from code that both analyzes and manipulates layout. A database that is both efficient and aware of on-the-fly manipulations is practically impossible to build. The Region class is essentially the core feature for DRC - which is a classical "analysis-only" function. Optimizations include not copying the data if not needed. The Region class also employs caching (for example for the merged polygons which are the basis of "area"). As Region is not aware of manipulations, it will not invalidate the cache and the area value derived from that will stay the same.

    If you want to force a Region into detached state, you can use "flatten" for example. This gives you a flat collection of polygons, independent of the original layer, but also will potentially use a lot of memory.

    Matthias

  • edited October 11

    ChatGPT is not clear to me: Regions do not represent the shapes as they were initially defined... my example above demonstrates exactly the contrary.
    If I decipher your answer, it seems that Regions should be considered in undefined state if the design is modified after their definition, except if the Region has been flattened. Right?

    My advice is to stay away from code that both analyzes and manipulates layout

    Sorry, I don't understand what you mean. Are you saying that Regions should not be used for building new shapes in the design (merging, intersections, sizing, ...)? I though it was the most efficient way to go.

  • Hi @ocasta,

    Good. I don't understand ChatGPT either :)

    What I mean by my statement is the following: when you create a Region from an original layer, there normally is no need to create a copy. A copy is only needed when you manipulate the layer, because you do not want to manipulate the original layer.

    But if you're changing the layout, the original data will change and hence the Region. To mitigate that, KLayout would need to keep a list of Region object clients and inform them about a change in the Layout. That means additional bookkeeping, servicing callbacks, managing clients (thread-safe preferably) etc. This adds overhead to the database design.

    As this is not required in the intended application (DRC), the design does not include features to support parallel manipulation of the Layout database while Region objects are in place to read it. In fact, original layer Regions may become not just modified, but there is a change that the application will crash if you access an original layer region after the Layout has been modified.

    If you absolutely need to keep a region, consider using "flatten" to detach it from the original layer:

    iter = cell.begin_shapes_rec(layout.find_layer(2,0))
    iter.maxdepth = 0
    r = pya.Region(iter)
    # detach the Region from the original layer
    r = r.flatten()
    

    BTW: if layer "2/0" does not exists (i.e. is empty), you application will throw an exception. Instead of "find_layer" you can simply use "layer" which will create a layer if it is not there yet.

    Matthias

Sign In or Register to comment.