How to "Deep copy" an instance

Hi! When I try to copy an instance, if I use new_instance = instance.dup, the returned object's Hash value is same as the original one. That means if I modify new_instance, the original instance will change at same time. I tried many times to get a "full copy" ,but all failed. Could you please help me? Thanks.


  • In the Navigator pane, when you copy a master (not instance, of)
    it will ask you whether you want to make a deep or shallow copy.

    Maybe you want to duplicate the master, not the instance, and
    make it uniquely named.

    If you want to change contents of used cells below, then you
    can either duplicate masters that get used, or duplicate the
    entire hierarchy.

    Somebody else will have to tell you -how- to duplicate the
    master in scripting.

  • Hi,

    You could duplicate the cell you want to copy deep and all of its called cells as well. Then, inside these duplicated cells you make all the instances point to these newly duplicated cells... Not sure if there is a method who does this on the fly...



  • @Default I think you mean when scripting, right?

    Problem is that "dup" will create a copy in the Python/Ruby sense, but the underlying "Instance" object still acts as a pointer into the database. That is the nature of the object and dup does not change that.

    I wonder what "deep copy" means. In the hierarchical sense, a deep copy means that if you copy an instance to a cell A you expect A to be copied (e.g. to A2) and then the new instance points to this cell. So you can modify the new A2 cell without changing layout on the other places.

    If you mean deep copy in the programming sense, you create another instance (with different location etc.) to the same cell. This you can do by using the "CellInstArray" object which is the actual instance data structure:

    # gets a copy of the data structure -> CellInstArray
    cia = instance.cell_inst()
    ... modify the CellInstArray object as you wish
    # insert the modified instance as a new cell instance:

    In the documentation "CellInstArray" is sometimes referred to as the "working object". This means a detached data structure that describes an object. "Instance" is the same thing, but living inside the database. So "Instance" is rather a reference or a pointer.

    BTW: the same concept applies to "Shape" (the reference/pointer to a geometrical primitive) and the working objects ("Box", "Polygon", "Path" etc.).


  • Thank you Matthias!
    But I have an another question:Shape class has no cell_inst(),If I want to duplicate a shape object(not point to same shape in database),What should I do?Thanks a lot!

  • That depends what you want to do.

    I understand that you want to modify the object. A plain copy does not make much sense, right?

    So when you want to copy-and-modify and shape, you need to focus on a specific shape type. Most shape types (with the exception of texts) can be converted into a polygon. That is the working object for this kind of shape like CellInstArray is for instances. So the code is like this:

      if not shape.is_text():
        polygon = shape.polygon
        # ... do something with polygon ...
        shapes.insert(polygon)   # insert the modified polygon

    (Side note: if you want to transfer an object you can also insert the Instance or Shape object into a new different or Shapes container respectively).


  • Another option could be to Flatten and then Make Cell. You can pick levels and do it top down, push and pop, if the complexity is low. This is something I've found efficient (but it's all manual, not scripted).

    So do you need a script to generalize this activity or ease it in the future? Or just get it done one time, for now?
  • For a user deep copy means that the entire tree is copied and converted to new cells (with different names in the database, because this is what you need when you want to change the sub-tree later without affecting the original tree). What I see right now is that when I try to deep copy with "dup" some aspects are copied and some are not (pointers vs. objects). So if I want a deep copy the easiest way is to write the cell as OASIS file, then read it in with 'AddToCell' in the reader option:
    reader_options.CellConflictResolution = reader_options.AddToCell
    This is 2 lines of code for me.
    Then all cells in the hierarchy show up with different names and can be changed separately.
    Using "flatten" is really bad, as it destroys the existing hierarchy. Selectively you can "resolve" arrays and maybe flatten one level of a cell but this didn't work for me with Python scrypting. Basically, I can resolve arrays in the GUI but if I try to resolve the cells in a script my database got corrupted (I suspect it was because I got the pointers from a RecursiveInstanceOperator). I am still trying to understand this, I think you need to know your database hierarchy and also know where you want to go.

    If you don't know your database and get information from the RecursiveInstanceIterator, I think you can't change/delete the objects in the iterator, so I suspect one way of doing it is to identify the objects in the iterator first (with their .to_s() function) and then use the single level iterators in the cells to find this string and then do something with the object.

    Note that the scripting features in KLayout (with Python) are on a completely different level compared to other tools using Lisp or Tcl especially with Neovim or VS Code as IDE, so you have the power.

Sign In or Register to comment.