Closed quaeritis closed 5 years ago
Hi,
Here is some explanation:
"l" is a "LayerInfo". This object provides the description of the layout layer in the layout file. This is the "canonical" way of describing a layer. A GDS file describes a layer in terms of layer and datatype number. Hence "l" features a layer and datatype number. This layer number is what you get when you use "l.layer". Some formats (like DXF or CIF) use names instead of numbers, hence there also is a "name" attribute in "LayerInfo".
"l_layer" is the layer index (sorry for the ambiguity). Internally, KLayout keeps a list of layers and the layer index identifies a layer in this list. Typically there is a correspondence: when you loaded a layout, each layout layer corresponds to one layer in this list. The order isn't specified, so GDS layer 10 may correspond to layer index 3 or anything else. There may also be layout layers that don't correspond to layers in the layout file (temporary or internal layers).
All methods that access shape information work with layer indexes. "l.layer" isn't this index, but the format layer number that helps finding this layer in the actual layout. As PCell parameters, GDS layer/datatypes or layer names are used, because these are independent on the actual internal order of the layer list. "l_layer" is a convenience shortcut to the layer index.
"layout.layers" is the number of layers in the layout. This will also include hidden internal layers (e.g. the layer for the guiding shapes). "layout.layer_indexes" gives a list of all layer indexes of non-hidden layers.
So bottom line is you should declare a parameter (i.e. "l") with layer type. Then use "l_layer" (parameter name + "_layer") to get the internal layer index of this layer.
Matthias
Hi,
thank you first for the quick help.
my code now looks like this:
import klayout.db as pya
class BasicSample(pya.PCellDeclarationHelper):
def __init__(self):
super(BasicSample, self).__init__()
self.param("l", self.TypeLayer, "Layer", default = pya.LayerInfo(0, 0, "silicon"))
self.param("size", self.TypeDouble, "Sample size", default = 7000)
self.param("columns", self.TypeInt, "Number of columns", default = 3)
self.param("lines", self.TypeInt, "Number of lines", default = 3)
def produce_impl(self):
print("self.l_layer:", self.l_layer)
#start_layer = 0
#layer_index = self.layout.layer(start_layer, 0, "silicon")
#print("layer_index:", layer_index)
self.cell.shapes(self.l_layer).insert(pya.Box(0, 0, self.size, self.size))
frame_size = 800
width = (self.size-2*frame_size)/self.columns
height = (self.size-2*frame_size)/self.lines
bx = 0 + frame_size
by = 0 + frame_size
tx = width + frame_size
ty = height + frame_size
index = self.l_layer+1
#print("i", layer_index)
for column in range(1, self.columns+1):
for line in range(1, self.lines+1):
layer_info = pya.LayerInfo(index, 0, "c%i%i_l%i" % (column, line, index))
layer_index = self.layout.insert_layer(layer_info)
#layer_index = self.layout.layer(index, 0, "c%i%i_l%i" % (column, line, index))
print("make a new box on new layer: index: %i, c%i%i, at cor %8.1f %8.1f %8.1f %8.1f, " % (index, column, line, bx, by, tx, ty))
print("layer_index", layer_index)
print("is_valid_layer:", self.layout.is_valid_layer(index))
print("is_valid_layer:", self.layout.is_valid_layer(layer_index))
self.cell.shapes(layer_index).insert(pya.Box(bx, by, tx, ty))
index = index+1
by = by + height
ty = ty + height
bx = bx + width
tx = tx + width
by = by - self.lines*height
ty = ty - self.lines*height
class TestLib(pya.Library):
def __init__(self):
self.description = "BasicSample"
self.layout().register_pcell("BasicSample", BasicSample())
self.register("BasicSampleLib")
# create and register the library
lib = TestLib()
# --------------------------------------------------------
# Client code
lay = pya.Layout()
top = lay.create_cell("TOP")
output_file = "test.oas"
#para = { "l": pya.LayerInfo(1, 0) }
para = { }
pcell = lay.create_cell("BasicSample", "BasicSampleLib", para)
trans = pya.DCplxTrans.new(1, 0, False, 0, 0)
top.insert(pya.DCellInstArray(pcell.cell_index(), trans))
lay.write(output_file)
Unfortunately, this only works for default = pya.LayerInfo (0, 0," silicon ")
and not for default = pya.LayerInfo (1, 0," silicon ")
or others.
For me it was irritating that I got l_layer = 0 with pya.LayerInfo (1, 0)
.
I think it would be useful that the attempt not to generate valid layer would cause an exception or?
In the doc I have found different names:
layer
== format layer number
layer_index
== layer index
index
== layer index?
From self.l_layer
can I get layer_index
?
layer_index
I need for self.cell.shapes
the doc says I get from layout.layer
only "layer" and from insert_layer
layer_index
?
So I should work with layer_index
if possible?
(sorry for my bad English)
best regards quaeritis
To wrap this up:
If you define a parameter (say "x") and give it "TypeLayer", then you will have these options in your code:
x
: the LayerInfo
object (not quite useful, except for printing the layer)x.layer
: the GDS layer for (also not quite useful). Also: x.datatype
, x.name
.x_layer
: the layer index (very useful, because with this you address the layer in the layout)Can I close this issue with this explanation?
Hello,
I'm trying for a while to play around with the klayout python module. Unfortunately, there seems to be some problems.
What is the subject between self.l_layer and self.l.layer? self.l_layer and the return value of insert_layer sometimes seem to return a "wrong" integer value but deliver the right value when passed to a function?
layer_index here is 3 but the layer is created at 10. Should self.layout.layers not return an integer?
It sometimes seems to make a difference whether pya.LayerInfo or pya.LayerInfo.new is used, what is the difference?
Unfortunately I could not narrow down the problem yet.
outbut:
Another example, here is a big box with smaller boxes in the middle to be generated that are ever on other layers. So far I've always had some problems with the layers, am I doing something wrong?
best regards quaeritis