Select a cell and change layer

Helo,

I am very new to Klayout scripting and would like to write my first script (ruby and/or python) which does the following:

Select a cell in a layout using cell name (e.g. “example_cell”) and change gds layer from original layer to a new layer (e.g. change from layer 112/2 to layer 101/1).

I have written the following code to generate the new gds layer (don’t know if it is the best way to do it but it works), now I’m missing the part to select cell “example_cell” and change gds layer.

app = RBA::Application.instance

mw = app.main_window

layout_view = mw.current_view

layer_info = RBA::LayerInfo.new(101,1)
layer_pn = RBA::LayerPropertiesNode::new

layer_pn.source = layer_info.to_s
layout_view.insert_layer( layout_view.end_layers, layer_pn )

Thanks for support.

Comments

  • edited May 2019

    Hallo,

    Here is some sample script (Python). With other values, but the comments should make it easy to adjust the script:

    # fetches current layout view and cell view
    view = pya.LayoutView.current()
    cellview = pya.CellView.active()
    
    # gets the corresponding layout object
    layout = cellview.layout()
    
    # gets the cell to change is "INV2X"
    cell_to_change = layout.cell("INV2X")
    
    # finds source layer: GDS layer 1, datatype 0
    source_layer = layout.layer(1, 0)
    
    # finds (or creates) target layer: GDS layer 10, datatype 0
    target_layer = layout.layer(10, 0)
    
    # gets the Shapes object which holds the shapes of a cell/layer
    # for source:
    source_shapes = cell_to_change.shapes(source_layer)
    # for target:
    target_shapes = cell_to_change.shapes(target_layer)
    
    # moves shapes
    target_shapes.insert(source_shapes)
    source_shapes.clear()
    
    # makes sure the new layer is shown
    view.add_missing_layers()
    

    Matthias

  • Hello Matthias, thanks for your feedback!

  • Is there a way to modify this code for when cell_to_change has nested subcells and you want to update the layer for shapes within all subcells? It seems that begin_shapes_rec should be able to help but I get nothing but syntax errors in spite of reading the manual.

    (By the way, is there a manual for how to parse the manual? I find the manual to be rather opaque in spite of having taken some online Python object-oriented programming courses.)

  • edited October 2022

    I don't think a RecursiveShapeIterator is what you want. If you did that, you will flatten the cell effectively (on the layer you want to swap from). And as with many iterators, it is a bad idea to delete the objects you are iterating over. If you want to swap layers for all the cells below, you should use something like cell.each_child_cell() and do the trick Matthias mentioned above. Out of the top of my head, I am not sure whether the child cells are strictly one hierarchy level below the cell or all the hierarchy levels. In the second case you just have to write it with recursion.


    The reason the manual doesn't seem intuitive is because first and foremost the classes and objects come from C++ (and Qt for the GUI stuff) and are not necessarily (and often not) written in a phythonic way. The python/ruby classes are afaik mainly wrappers around the C++ objects (based on Python.h if I interpreted the source code correctly when I looked at it). Therefore, the iterator is most similar to a C++ iterator and not a Python iterator and you have to handle it accordingly. For some classes you can treat them like generator objects in python, but not the recursive ones:

    So this will not work:

    shape_iterator = cell.begin_shapes_rec(layer_index)
    
    for shape in shape_iterator:
       #do stuff with the shapes here
    

    You have to iterate like you would do in a C++ loop (i.e. check whether the iterator is at the end and increment at the end of each loop).

    The python code looks something like this

    shape_iterator = cell.begin_shapes_rec(layer_index)
    while not shape_iterator.at_end():
        shape = shape_iterator.shape()
        # do stuff with the shape
        shape_iterator.next()
    

    If an object has .each() (or similar) then you can treat them like a generator object in python, i.e. for loops work on them.

  • Thank you, Sebastian, for the tip on my specific code issue and also on the documentation and C++.

    My mind went to the shape iterator because

    bounding_shapes=Pya.Shapes()
    bounding_shapes.insert(cell_to_change.begin_shapes_rec(bounding_layer))
    

    works without an explicit while (or for) loop. To me insert and delete or clear all feel like close relations, but they don't seem to interact in parallel ways with the RecursiveShapeIterator

  • @sebastian Thanks for these explanations also from my side. The reason why the recursive shape iterator does not have "each" is basically that the shape itself isn't quite useful - you will also need the current cell, the transformation into the initial cells, the layer (for multi-layer iterator) etc. That is why the recursive shape iterator isn't "pythonic".

    @ehs73 It's true that "insert" works with recursive shape iterators. It will internally perform the loop including propagating the shape into the (flat) shape collection. But that is a pure "feed" operation and not related to "delete" for example.

    If you would be so kind and paste some example code we could take a look at it together.

    Matthias

Sign In or Register to comment.