Not signed in (Sign In)

Vanilla 1.1.4 is a product of Lussumo. More Information: Documentation, Community Support.

    • CommentAuthorklfun
    • CommentTimeJun 3rd 2014
     
    Hi Guru, I want to generate a bitmap according to polygon patterns on GDS. Is there any scripting API for the purpose?
    Thank you for your attention!
    • CommentAuthorklfun
    • CommentTimeJun 3rd 2014
     
    Hi Matthias,

    I just searched through the forum tickets and found that you ever made the answers as follows:
    http://klayout.de/forum/comments.php?DiscussionID=327&page=1#Item_0
    Is it workable to my purpose?
    If yes, can you teach me how to set the pixels? Thru the width and height parameters?
    • CommentAuthorMatthias
    • CommentTimeJun 3rd 2014
     

    Hello,

    the answer depends on your application. The approach is suitable to create bitmaps for visualization purposes. If you want to feed the bitmaps into some mask writer tool for example, you may require a higher quality output.

    You can set the pixel dimensions of your result bitmap using the width and height parameter of the final image production call:

    view.save_image("#{output_file}", width, height)
    

    Matthias

    • CommentAuthorklfun
    • CommentTimeJun 4th 2014
     
    Hi Matthias,

    Yes. My application requires high quality output. I want to feed the bitmap (image) into some simulation engine.
    Can you teach me the way to achieve that?

    Thanks
    • CommentAuthorMatthias
    • CommentTimeJun 4th 2014 edited
     

    Well, bitmaps for visualization do not reflect pattern densities - the focus is on showing "something". Hence a pixel is set if some shape is on that pixel, but the pixel does not say much about the density at this point.

    If you want a bitmap that reflects the density (that's probably a gray map) you have basically two choices:

    • Use a big image with heavy oversampling to detect the details
    • Create a real density map

    Explaining the second option is somewhat beyond a simple forum entry. You'll have to become familar with the DRC feature and Ruby scripting. A forum entry related to density maps is this one: http://klayout.de/forum/comments.php?DiscussionID=167.

    Matthias

    • CommentAuthorklfun
    • CommentTimeJun 5th 2014
     
    Thanks Matthias. I'll try with your current instructions first.
    Is there any notable difference between the two choices? Runtime performance for example.
    • CommentAuthorMatthias
    • CommentTimeJun 5th 2014 edited
     

    Hi,

    Yes, there will a major difference in runtime, but also in quality.

    The image approach will just deliver binary information and does not care much about precision - if there is a very small shape, you will see one bright pixel, or maybe two or maybe even four. So if you count the pixels and treat them as a physical property, i.e. in the sense of an area density, you will get a value of 1 to 4.

    The density map will deliver a true pattern density. So for a very small shape you will get a density value which is proportional to the covered part of the pixel. So you might get values far below 1 for very small shapes which is a better measure for the effect of a small shape. Or if a shape covers half of a pixel, you will get a value of 0.5 and not just a binary value of 0 or 1, which more precisely reflects the contribution of the shape to that pixel.

    But the price to pay for precision is CPU time: the density method is much slower than the imaging method, although it's difficult to tell numbers. It's possible to run the density map on multiple cores to mitigate the effect a little.

    Matthias

    • CommentAuthorklfun
    • CommentTimeJun 6th 2014
     
    Hi Matthias,

    Quoted: "It's possible to run the density map on multiple cores to mitigate the effect a little."
    Did you mean that klayout supports distributed computation? How to trigger the parallel computing?

    Thanks
    • CommentAuthorMatthias
    • CommentTimeJun 9th 2014
     

    There is no global switch, but there is the "TilingProcessor" class which allows distributing the density computation to multiple cores. This class is not straightforward to use however and it cannot produce image files currently. But if you need CSV output for the density map for example, there is a way to do it.

    Matthias

    • CommentAuthorklfun
    • CommentTimeJun 9th 2014
     
    Hi Matthias,

    One more question:
    If we use the method in http://klayout.de/forum/comments.php?DiscussionID=167., we also need to clean the shape-to-shape overlap first, right? The action was not addressed in the entry.

    Thanks
    • CommentAuthorMatthias
    • CommentTimeJun 9th 2014
     

    No, that's already done in the "ep.merge(..)" call.

    BTW: the code in the forum entry works, but there are more efficient methods in between. Specifically there is the "Region" class which is basically a collection of polygons and provides more efficient ways to do the clipping, merging and collection of the area. And there is the tiling processor which controls the process and offers multi-code support for example.

    The tiling processor directly interfaces with the image class, so the code is pretty lean:

    view = RBA::LayoutView::current
    cv = RBA::CellView::active
    cv || raise("No layout selected")
    
    ly = cv.layout
    cell = cv.cell
    
    tp = RBA::TilingProcessor::new
    
    # TODO: adjust tile size
    tp.tile_size(20.0, 20.0)
    
    img = RBA::Image::new
    tp.output("image", img)
    
    # TODO: adjust input layer (here: layer 10, datatype 0)
    tp.input("input_layer", ly, cell.cell_index, RBA::LayerInfo::new(10, 0))
    
    tp.queue(<<END)
    var bx = _tile.bbox;
    var a = input_layer.area(bx);
    _output(image, to_f(a) / to_f(bx.area))
    END
    
    # TODO: adjust number of cores (here: 2)
    tp.threads = 2
    
    tp.execute("Density map")
    
    # TODO: save data to a file etc.
    view.insert_image(img)
    

    Maybe that is a more convenient solution in your case.

    Matthias

    • CommentAuthorklfun
    • CommentTimeJun 9th 2014
     
    Thanks Matthias. Your tool is amazingly powerful!
    So, the new method also takes the overlap clean into account?
    And, the device I need to tackle is composed of several layers by boolean. Do I need to make a new layer by perform boolean operations over the original layers first and then extract the density map from the "new layer"? I guess there is smarter way.
    • CommentAuthorMatthias
    • CommentTimeJun 10th 2014 edited
     

    Hello,

    yes, the area function will take overlaps into account - it will merge the shapes prior to computing the area.

    You can embed boolean operations too. They will be executed on the tiles and on multiple cores which makes them more efficient:

    ...
    # TODO: adjust input layer (here: layer 10, datatype 0)
    tp.input("input_layer1", ly, cell.cell_index, RBA::LayerInfo::new(10, 0))
    # TODO: adjust input layer (here: layer 11, datatype 0)
    tp.input("input_layer2", ly, cell.cell_index, RBA::LayerInfo::new(11, 0))
    
    tp.queue(<<END)
    var bx = _tile.bbox;
    var a = (input_layer1 & input_layer2).area(bx);
    _output(image, to_f(a) / to_f(bx.area))
    END
    ...
    

    This sample code will compute a boolean AND between layer 10 and 11 (each datatype 0). The boolean operator is "&" which represents the boolean AND. There are more operations available: "+" (OR), "-" (NOT) and "^" (XOR). You can even do a sizing (biasing) but that involves clipping and collection of the neighborhood which is another topic not covered here.

    Just in case you're curious: The magic is inside the "tp.queue" argument. This is a script executed for each tile. The variables specified in "input" are Region objects http://www.klayout.de/doc/code/class_Region.html. The script itself is not Ruby but KLayout expression syntax http://www.klayout.de/doc/about/expressions.html.

    You find more information about the tiling processor concept in the description of that class: http://www.klayout.de/doc/code/class_TilingProcessor.html.

    Matthias

    • CommentAuthorklfun
    • CommentTimeJun 12th 2014
     
    Matthias, awesome! Thank you!
    • CommentAuthorklfun
    • CommentTimeJun 16th 2014 edited
     
    Hi Matthias,

    If there were multiple top cells, should I execute multiple "tp.input"?
    like > tp.input("input_layer1", ly, cell.cell_index, RBA::LayerInfo::new(10, 0))

    If I should, can I assign all the cell into a same "input_layer", the first parameter of tp.input??

    Thanks
    • CommentAuthorMatthias
    • CommentTimeJun 17th 2014
     

    Hi,

    To execute the script on multiple cells, you will have to start with each cell.

    The sample script above takes the currently selected cell for input.

    You can iterator over all top cells this way:

    ly.each_top_cell do |tc_index|
    
      cell = ly.cell(tc_index)
    
      tp = RBA::TilingProcessor::new
      ...
    
    end
    

    Regards,

    Matthias

    • CommentAuthorklfun
    • CommentTimeJun 18th 2014
     
    Hi Matthias,

    Would the followings work? Not creating new TilingProcessor object but just defining different layers for different cells.

    ...
    tp = RBA::TilingProcessor::new
    tp.input("input_layer1", ly, cell.cell_index1, RBA::LayerInfo::new(10, 0))
    tp.input("input_layer2", ly, cell.cell_index2, RBA::LayerInfo::new(10, 0))
    ...
    tp.queue(<<END)
    var bx = _tile.bbox;
    var a = (input_layer1 & input_layer2).area(bx);
    _output(image, to_f(a) / to_f(bx.area))
    END
    ...

    Thanks
    • CommentAuthorMatthias
    • CommentTimeJun 18th 2014
     

    Hi,

    I guess this works. There is no restriction about the origin of the layout - neither layout, cell or layer.

    I think it will take the common bounding box as the total area to cover. But I have not verified that yet.

    Matthias

    • CommentAuthorklfun
    • CommentTimeAug 11th 2014 edited
     
    Dear Matthias,

    In your way of "Creating a real density map", it can be deemed that "anti-aliasing" has been considered, right? It is equivalent to "anti-aliasing + down-sampling". And then we can directly generate a density map at wanted pixel size using your way and then feed it into simulation engine. Am I right?

    Thanks,
    • CommentAuthorMatthias
    • CommentTimeAug 14th 2014 edited
     

    Hi,

    it is, if we have the same idea of "anti-aliasing". The density map will reflect the area covered by layout for each pixel. That is one possible way of defining some layout metrics on a coarser grid and it's easy to implement.

    It will also give you the right area coverage for very big pixels. But it's very difficult to tell whether the area coverage is an appropriate metric for your simulation. The nature of the input required depends on the kind of simulation, so I can't give a recommendation here without further knowledge about your application.

    Matthias

    • CommentAuthorklfun
    • CommentTimeAug 14th 2014
     
    Thanks Matthias.
    My application is doing optical simulation of imaging whose input patterns were defined by GDS. To implement simulation, I need to downsample the pattern first to get the map. By your way, I can get the map at the desired pixel size but I am not sure whether the operation is sufficient in terms of accuracy.

    Thanks,
    • CommentAuthorMatthias
    • CommentTimeAug 14th 2014 edited
     

    Hi,

    downsampling is always some approximation, but area density is probably the best you can do.

    A assume you want to use the grayscale value in the sense of some "transmission". But you need to be somewhat careful with the definition - under incoherent conditions the transmission scales intensity while under coherent conditions, the transmission scales the electric field and intensity is proportional to the square of that transmission.

    However, for practical application that difference probably does not matter much.

    Matthias

    • CommentAuthorklfun
    • CommentTimeAug 15th 2014
     
    Dear Matthias,

    Just to confirm: "area density" is the "real density map" by the way you proposed as below, right?
    -------------------
    tp.queue(<<END)
    var bx = _tile.bbox;
    var a = input_layer.area(bx);
    _output(image, to_f(a) / to_f(bx.area))
    END
    -------------------

    Thanks a lot for your reminder of the difference between coherent and incoherent! I should keep this in mind.

    Best Regards,
    • CommentAuthorMatthias
    • CommentTimeAug 16th 2014 edited
     

    Hi,

    That's right. That is the best that you can get with the scripting approach right now.

    Please note that the performance is not very good for small pixels, because every pixel is computed on its own. There is a routine inside KLayout which can render a polygon set to a grayscale map in an area density way using a single sweep. This method is much more efficient for small pixels and is also accurate, but there is not scripting interface to that method yet.

    Matthias

    • CommentAuthorklfun
    • CommentTimeAug 17th 2014 edited
     
    Thanks Matthias.
    I got your points.

    Best Regards,
    • CommentAuthorklfun
    • CommentTimeDec 30th 2016
     
    Hi Matthias,

    As you commented loooooog ago, there is a method much more efficient but no scripting interface supported.
    May I ask that whether the quick method has scripting interface now?

    Thanks
    • CommentAuthorMatthias
    • CommentTimeJan 4th 2017
     

    Hi klfun,

    I'm sorry - polygon grayscale rendering is still not part of the scripting interface. I also think that in general scripting isn't the right approach for high throughput, if you're interested in that.

    Regards,

    Matthias

    • CommentAuthorklfun
    • CommentTimeJan 5th 2017
     
    Thanks Matthias.
    Yes, I do need a way of high throughput. Could you please teach me how to use the non-scripting way then?
    • CommentAuthorMatthias
    • CommentTimeJan 7th 2017
     

    Hi klfun,

    For high throughput, there is no way around C++ coding.

    However, the internal API's are not well documented and not easy to use. Teaching you how to do this is beyond my commitment here - you have to study the code yourself.

    But even more important, the C++ code is subject to the terms of the GNU Public License (GPL). That means, when you pick code from there, include headers and even link against it, you are obliged to publish the derived work under GPL as well.

    Matthias

    • CommentAuthorklfun
    • CommentTimeJan 9th 2017
     
    Thanks Matthias. Understood.
    • CommentAuthorklfun
    • CommentTimeFeb 9th 2017
     
    Dear Matthias,

    Can I get a hint about where to find the routine? I can find gsiDeclImg.cc, but not sure whether it is the right to start with.

    Thanks
    • CommentAuthorMatthias
    • CommentTimeFeb 12th 2017
     

    There is a "rasterize" method in dbPolygonTools.h, which may be a starting point. But I doubt whether it's well tested.

    Please observe the GPL requirements.

    Matthias