Forum Replies Created
-
AuthorPosts
-
paulMember
Thank you Solution 2 works great! Didnt have an opportunity to test it until now..
I have added a layermapmode argument to
custombuild()
so that it can be passed tond.layout()
for filtering unwanted layers.paulMemberHi Ronald,
Thanks for your answer. Yes your solution works and I have been using the same idea so far, only that it isnt very flexible as export_gds() must be called whenever the layermap changes.
Say that I have a cell, CellA, which must be placed at different locations on the wafer and on different layers. My idea was to create a generic CellA on a dummy layer and then instantiate it on the approriate layer.
For instance, if I wanted to create an array of cells based on CellA placed on different layers, the code would look like:
with nd.Cell(name='CellA') as cellA: nd.strt(length=2, width=2, layer=0).put() grid_points = [(0, 0), (4, 0), (0, 4), (4, 4)] for i, (x,y) in enumerate(grid_points): # cellA.put(x,y) new_cell = cellA.rebuild(layermap={0:i}) # this is the intended usage, doesnt currently work new_cell.put(x,y) nd.export_gds()
where each “copy” of cellA would be on a different layer.
Of course, there are more efficient solutions for such a simple design, but I’d like to use this mechanic for importing generic cells from a gds file and do the layermaping in nazca. For now, I’m using something like :generic_cell = 'path_to_generic_cell.gds' # a gds file containing generic cell placed on layer 0 for i, (x,y) in enumerate(grid_points): new_cell = nd.load_gds(generic_cell, layermap={0:i}) new_cell.put(x,y)
This isn’t really efficient as I must reimport the file for each layer. That’s why I thought that importing it once and remapping in Nazca would be a better idea.
Thanks,
Paul
paulMemberThanks Ronald, I came across this function yesterday whilst browsing the manual but hadn’t had time to try it out. Looks very powerful.
paulMemberHello Ronald,
Yes I think that it does cover it, because in a normal use case I would instantiate the new cells as top cells and then instantiate them in the hierarchy manually in Klayout (usually by replacing old cells).
import nazca as nd # Level 1 Cells with nd.Cell(name='B') as cellB: nd.strt().put() with nd.Cell(name='C') as cellC: nd.bend(angle=90).put() with nd.Cell(name='D') as cellD: nd.taper(layer=2).put() # Level 0 Cell (top cell) with nd.Cell(name='A') as cellA: cellB.put() cellC.put(10) nd.export_gds(filename='example.gds', topcells=cellA) # Load example.gds, and add cellD as a top cell cell_dict = nd.load_gds(filename='example.gds', asdict=True, topcellsonly=True) cell_list=list(cell_dict.values()) cell_list.append(cellD) nd.export_gds(filename='example.gds', topcells=cell_list)
In the example above, I could either manually instantiate cell D as a new cell in cell A, or replace of the existing cells by cell D after the second export.
To push things further how could I automatically replace the cells in Nazca? In the example below I tried to replace cell C with a new version in the cell dictionary. It does not replace the old cell but instantiate it as a new top cell.
import nazca as nd # A new version of cellC with nd.Cell(name='C$1') as newC: nd.bend(angle=30, layer=3).put() # topcellsonlly flag set to False to import old cell C cell_dict = nd.load_gds(filename='example.gds', asdict=True, topcellsonly=False) # replace cell C in cell_dict cell_dict['C'] = newC # get new list of cells cell_list=list(cell_dict.values()) nd.export_gds(filename='example_v2.gds', topcells=cell_list)
The obvious answer would be to recreate the whole hierarchy, i.e in this case:
newCellA newCellC oldCellB oldCellD
But this can get tedious if you need to replace a cell in the lowest level of the hierarchy, or even worse if the cell is instantiated in different ‘tree branches’.
Thanks,
Paul
nazca version: 0.5.7
paulMemberDear Ronald,
Thanks for the detailed answer. This is exactly the sort of function I was after and I think that this post will be helpful when it comes to creating custom Interconnect shapes.
With 0.5.4 this line
for lay, grow, acc, line in nd.layeriter(xs, layer):
returned a ValueError: not enough values to unpack (expected 4, got 3), so I commented theline
parameter out since it wasn’t being used anywhere in the loop.Thanks,
PaulpaulMemberThank you, I suspected that this was something as trivial as this!
paulMemberDear Xaveer,
Thank you very much!
Paul
paulMemberHi Ronald,
That’s a very good question, as I know that my current solution will only get me this far. But as you said it’s a first step and it allows me to push on with my design. What I like though, is that it should work for any path, not just the sbend shown here.
I’m still planning on looking at parametrizing the curve by arc length once I have more time. Will post the outcome here if successful.Cheers,
Paul
paulMemberHi Xaveer,
I’m using Nazca 0.5.1
In the end I was looking at the problem sideways, that’s what I got confused.
Just wanted to make sure that I understood the function properly before using it.Cheers,
Paul
paulMemberThanks Ronald,
I have found a quick and ugly way of doing it by calculating the line integral along the path. Whenever the distance gets bigger than an multiple of my desired spacing, I place the desired geometry. This works as long as the curve is defined with enough points.
xy = nd.curve2polyline(nd.sinebend_point, (100, 20, 0), 0.0001, (100, 20)) x, y = map(list, zip(*xy)) dl = 0 # element of length lint = 0 # total integral k = 1 spacing = 10 # desired spacing for i in range(1, len(y)): dl = np.sqrt((x[i] - x[i - 1]) ** 2 + (y[i] - y[i - 1]) ** 2) lint += dl if lint > k * spacing: hole.put(x[i], y[i]) k += 1 nd.export_plt()
paulMemberHi,
I would also be interested in designing something similar to this. How would you place the circle/squares along the path once it’s been created?
At the moment i’m thinking of using the nazca geometries library to create the shapes but I don’t see how I could place them periodically along a parametric path.
cheers,
Paul
-
AuthorPosts