<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Ruby Scripting — KLayout</title>
        <link>https://www.klayout.de/forum/</link>
        <pubDate>Fri, 13 Mar 2026 07:23:46 +0000</pubDate>
        <language>en</language>
            <description>Ruby Scripting — KLayout</description>
    <atom:link href="https://www.klayout.de/forum/categories/ruby-scripting/feed.rss" rel="self" type="application/rss+xml"/>
    <item>
        <title>Dark mode</title>
        <link>https://www.klayout.de/forum/discussion/2126/dark-mode</link>
        <pubDate>Sun, 31 Jul 2022 21:10:49 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>Matthias</dc:creator>
        <guid isPermaLink="false">2126@/forum/discussions</guid>
        <description><![CDATA[<p>Here is a nice script for those who love fancy "dark mode":</p>

<pre><code><br />palette = RBA::QPalette::new

palette.setColorGroup(RBA::QPalette::Active, 
  RBA::QBrush::new(RBA::QColor::new("#f0f0f0")),   # windowText
  RBA::QBrush::new(RBA::QColor::new("#303030")),   # button
  RBA::QBrush::new(RBA::QColor::new("#505050")),   # light
  RBA::QBrush::new(RBA::QColor::new("#707070")),   # dark
  RBA::QBrush::new(RBA::QColor::new("#909090")),   # mid
  RBA::QBrush::new(RBA::QColor::new("#e0e0e0")),   # text
  RBA::QBrush::new(RBA::QColor::new("#909090")),   # brightText
  RBA::QBrush::new(RBA::QColor::new("#202020")),   # base
  RBA::QBrush::new(RBA::QColor::new("#101010")),   # window
) 

palette.setColorGroup(RBA::QPalette::Inactive, 
  RBA::QBrush::new(RBA::QColor::new("#f0f0f0")),   # windowText
  RBA::QBrush::new(RBA::QColor::new("#303030")),   # button
  RBA::QBrush::new(RBA::QColor::new("#505050")),   # light
  RBA::QBrush::new(RBA::QColor::new("#707070")),   # dark
  RBA::QBrush::new(RBA::QColor::new("#909090")),   # mid
  RBA::QBrush::new(RBA::QColor::new("#e0e0e0")),   # text
  RBA::QBrush::new(RBA::QColor::new("#909090")),   # brightText
  RBA::QBrush::new(RBA::QColor::new("#202020")),   # base
  RBA::QBrush::new(RBA::QColor::new("#101010")),   # window
) 

palette.setColorGroup(RBA::QPalette::Disabled, 
  RBA::QBrush::new(RBA::QColor::new("#808080")),   # windowText
  RBA::QBrush::new(RBA::QColor::new("#303030")),   # button
  RBA::QBrush::new(RBA::QColor::new("#505050")),   # light
  RBA::QBrush::new(RBA::QColor::new("#606060")),   # dark
  RBA::QBrush::new(RBA::QColor::new("#686868")),   # mid
  RBA::QBrush::new(RBA::QColor::new("#707070")),   # text
  RBA::QBrush::new(RBA::QColor::new("#686868")),   # brightText
  RBA::QBrush::new(RBA::QColor::new("#202020")),   # base
  RBA::QBrush::new(RBA::QColor::new("#101010")),   # window
) 

RBA::QApplication::setPalette(palette)
</code></pre>

<p>Set the "run on startup" flag and enjoy night mode:</p>

<p><img src="https://www.klayout.de/forum/uploads/editor/bf/cmny4t26laul.png" alt="" title="" /></p>

<p>Matthias</p>
]]>
        </description>
    </item>
    <item>
        <title>Can we automate the process of merging layers?</title>
        <link>https://www.klayout.de/forum/discussion/1881/can-we-automate-the-process-of-merging-layers</link>
        <pubDate>Wed, 07 Jul 2021 07:55:43 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>philyu</dc:creator>
        <guid isPermaLink="false">1881@/forum/discussions</guid>
        <description><![CDATA[<p>I follow such steps: Edit -&gt; Layer -&gt; Merge<br />
<img src="https://www.klayout.de/forum/uploads/editor/4s/zwezm4qayu2f.png" alt="" title="" /><br />
Then I can merge layers. <br />
However, I want to automate this process by using Macro Development. I'd like to know which class or procudure I should use.</p>
]]>
        </description>
    </item>
    <item>
        <title>Ruby macro changes in editor not showing up when running</title>
        <link>https://www.klayout.de/forum/discussion/2829/ruby-macro-changes-in-editor-not-showing-up-when-running</link>
        <pubDate>Thu, 11 Dec 2025 22:15:04 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>dave_d</dc:creator>
        <guid isPermaLink="false">2829@/forum/discussions</guid>
        <description><![CDATA[<p>I have a ruby lym file and a rb file loaded in the macro development editor.<br />
I am using version 0.30.5<br />
Both files are in my \macros directory.</p>

<h1>the lym File:</h1>

<p>module TestMacro1<br />
  include RBA<br />
   require_relative 'C:\Users\david\KLayout\macros\helper'<br />
  # Enter your Ruby code here ..<br />
    a=4<br />
    b=helper(a)</p>

<p>end</p>

<h1>the rb file with a function I want to call</h1>

<p>include RBA</p>

<p>def  helper( a)<br />
   b=a+1<br />
   return b<br />
end</p>

<p>The first time I run it after starting Kayout, the helper() function gets called and returns 5.<br />
Now I edit the helper() function to set b=a+10. I save it with the buttons on the top of the left panel, and also<br />
right click on the helper function an click 'refresh'.</p>

<p>When I run TestMacro1.lym   (from green triangle with the exclamation point in the editor),  helper still sets b=5, not 14 reflecting the change.<br />
I can put break points in helper() and see the b variable be assigned to 5 even though the code says it should be a+10.<br />
If I add another line like 'c=9' before 'return b' in helper,  the function just exits and does not create the c variable.</p>

<p>How do we get the editor to save and use the edited version of the files.<br />
This was never a problem back in version 0.24.</p>

<p>I have tried running Klayout as administrator and closing and reopening the macro dev window.<br />
The only thing that works is closing and re-opening Klayout.</p>

<p>Thanks for any help.</p>
]]>
        </description>
    </item>
    <item>
        <title>How to export size of layer for over 1000 GDS files?</title>
        <link>https://www.klayout.de/forum/discussion/2812/how-to-export-size-of-layer-for-over-1000-gds-files</link>
        <pubDate>Thu, 06 Nov 2025 05:22:13 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>jiunnweiyeh</dc:creator>
        <guid isPermaLink="false">2812@/forum/discussions</guid>
        <description><![CDATA[<p>Hi sir,<br />
I have over 1000 GDSII files , in the each file , we have some information such as DIE size .<br />
Do you have any idea to load each file and exprot that data by script auto -batch ?</p>

<p>Export DIE size of current GDSII file is very easy.<br />
die=input(71,0)<br />
puts die.bbox.width<br />
puts die.bbox.height</p>

<p>but the key issue will be that , I have over 1000 GDSII file. and I need to export that data of each one.</p>
]]>
        </description>
    </item>
    <item>
        <title>Length values in expressions using TilingProcessor</title>
        <link>https://www.klayout.de/forum/discussion/2786/length-values-in-expressions-using-tilingprocessor</link>
        <pubDate>Thu, 18 Sep 2025 08:26:47 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>mole99</dc:creator>
        <guid isPermaLink="false">2786@/forum/discussions</guid>
        <description><![CDATA[<p>Hello, I have a question regarding the TilingProcessor and expressions.</p>

<p>I have the following (shortened) setup:</p>

<pre><code>tp = RBA::TilingProcessor::new
tp.frame = chip
tp.dbu = ly.dbu
tp.threads = threads
tp.tile_size(tile_size, tile_size)

tp.input("COMP", ly, top_cell.cell_index, COMP)
tp.input("Poly2", ly, top_cell.cell_index, Poly2)
tp.input("PMNDMY", ly, top_cell.cell_index, PMNDMY)

tp.var("space_to_COMP", 3.5 / ly.dbu)
tp.var("space_to_Poly2", 1.5 / ly.dbu)

tp.output("to_fill", TilingOperator::new(ly, top_cell, fill_cell.cell_index, fc_box_in_dbu, row_step_in_dbu, column_step_in_dbu, fc_origin_in_dbu))

tp.queue("
var COMP_20um_spacing = COMP.sized(20um).sized(-20um)
var fill_region = _tile &amp; _frame - COMP_20um_spacing.sized(space_to_COMP) - Poly2.sized(space_to_Poly2) - PMNDMY;
_output(to_fill, fill_region)")
</code></pre>

<p>I get the following error:</p>

<pre><code>ERROR: Worker thread: Length or area value with unit requires a layout context at line 3, position 36 (..20um).sized(-20um)
</code></pre>

<p>Which makes a lot of sense, however since the tiling processor has information about the dbu, shouldn't it be possible to convert the length value?<br />
Or is there another way to supply the layout context?</p>

<p>As a workaround I can supply the constant as a variable like I did for the spacing:</p>

<pre><code>tp.var("um20", 20 / ly.dbu)
</code></pre>

<p>Let me know if you need a full reproducible.</p>

<p>Thanks!</p>
]]>
        </description>
    </item>
    <item>
        <title>fill multiorigin and manufacturing grid</title>
        <link>https://www.klayout.de/forum/discussion/2620/fill-multiorigin-and-manufacturing-grid</link>
        <pubDate>Sun, 10 Nov 2024 00:52:53 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>tnt</dc:creator>
        <guid isPermaLink="false">2620@/forum/discussions</guid>
        <description><![CDATA[<p>So I'm calling something like <code>M4Fil.fill(pattern_m4s, hstep(width_m4s + distance_m4s), vstep(height_m4s + distance_m4s), multiorigin)</code> to generate a fill pattern.<br />
But how can I ensure that the selected origin matches the manufacturing grid of 5 nm ? Where do I set that ?</p>
]]>
        </description>
    </item>
    <item>
        <title>Klayout version update.</title>
        <link>https://www.klayout.de/forum/discussion/2773/klayout-version-update</link>
        <pubDate>Fri, 22 Aug 2025 02:50:23 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>jiunnweiyeh</dc:creator>
        <guid isPermaLink="false">2773@/forum/discussions</guid>
        <description><![CDATA[<p>Hi Sir,<br />
as mention before , I am an bumping designer and using Klayout to make some script to do something.<br />
currently , we using 0.28.12 , a little old version.<br />
I knew that your team upudate Klayout to 0.30.3 , and  I am under check all of script I maked if that is workable or not.<br />
What my questiion is , I knew that you have make a note and list to shown what gengie been updated or bugfix.<br />
BUT  , some of that is hard to line with my script , <br />
I don't know how to compare my existing scripts and programming with your notes....<br />
Is it possible to shown that more easy to read?</p>
]]>
        </description>
    </item>
    <item>
        <title>Degassing hole feature via ruby automation</title>
        <link>https://www.klayout.de/forum/discussion/2767/degassing-hole-feature-via-ruby-automation</link>
        <pubDate>Tue, 12 Aug 2025 04:53:51 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>Tushar_Mayank</dc:creator>
        <guid isPermaLink="false">2767@/forum/discussions</guid>
        <description><![CDATA[<p>I am looking to create a Ruby automation script for KLayout that can automatically place "degassing" holes within large metal fill areas. The goal is to replicate a feature similar to what is available in tools like Cadence Allegro.</p>

<p>I came across this Cadence forum post that describes the functionality I'm trying to achieve:<br />
<a href="https://community.cadence.com/cadence_technology_forums/pcb-design/f/allegro-x-apd/52353/degassing-with-apd" rel="nofollow">https://community.cadence.com/cadence_technology_forums/pcb-design/f/allegro-x-apd/52353/degassing-with-apd</a><br />
Can anyone help me out?</p>
]]>
        </description>
    </item>
    <item>
        <title>How to Identify Layer Types in a Complex GDS File for a cross- section?</title>
        <link>https://www.klayout.de/forum/discussion/2763/how-to-identify-layer-types-in-a-complex-gds-file-for-a-cross-section</link>
        <pubDate>Thu, 31 Jul 2025 19:26:12 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>Yessnr</dc:creator>
        <guid isPermaLink="false">2763@/forum/discussions</guid>
        <description><![CDATA[<p>I’m new to layout design and was assigned a task to generate a cross-section for a very complex layout. I have a GDS file with multiple cells and a layer list, but the layers aren’t labeled. I wrote a script to retrieve the layer names, but none were found. Is there a way to determine the layer types (e.g., metal, via, poly) programmatically? Can a script help identify these automatically?</p>
]]>
        </description>
    </item>
    <item>
        <title>inverting</title>
        <link>https://www.klayout.de/forum/discussion/2764/inverting</link>
        <pubDate>Mon, 04 Aug 2025 18:52:35 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>Yessnr</dc:creator>
        <guid isPermaLink="false">2764@/forum/discussions</guid>
        <description><![CDATA[<p>I keep getting this wrong number of arguments (given0, expected 1) for this pwell_implant = mask(nwell).not.grow(0.25, :mode =&gt; :round, :into =&gt; pbulk is there a different way to invert?</p>
]]>
        </description>
    </item>
    <item>
        <title>How can I see the violated values ​​in the info tab?</title>
        <link>https://www.klayout.de/forum/discussion/2718/how-can-i-see-the-violated-values-%E2%80%8B%E2%80%8Bin-the-info-tab</link>
        <pubDate>Fri, 16 May 2025 02:46:47 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>안준용</dc:creator>
        <guid isPermaLink="false">2718@/forum/discussions</guid>
        <description><![CDATA[<p>How can I see the violated values ​​in the info tab? And is there a way to filter the violated values ​​by min and max in the Markers tab??<br />
<img src="https://www.klayout.de/forum/uploads/editor/x0/4r43in2ae3hg.png" alt="" title="" /></p>
]]>
        </description>
    </item>
    <item>
        <title>progressbar.inc prevents proper target_view.update_content and layer property sets</title>
        <link>https://www.klayout.de/forum/discussion/2736/progressbar-inc-prevents-proper-target-view-update-content-and-layer-property-sets</link>
        <pubDate>Wed, 11 Jun 2025 14:12:05 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>tnoradam</dc:creator>
        <guid isPermaLink="false">2736@/forum/discussions</guid>
        <description><![CDATA[<p>Hi Matthias,<br />
I know you have abandoned the xSection module a long time ago, but we have developed it into an encompassing add-in that works well. Obviously, I cannot post the code here (wrote many many many extra things for it), but the output function has a progressbar that shows up after a second or two. In past versions of klayout (&lt; 0.30 ?), it worked well. In the newer versions, we had to comment the .inc out, and as a result, no progress bar is shown. This is because other calls that update the view and layers were somehow not executed while progress bar was active. This manifested itself as saved snapshots that were not zoomed correctly, and had layer properties that were assigned wrong (or not at all, not sure). The only thing that worked in the end is to disable the progressbar. Even if app.process_events is not ever called, the automatic step-by-step saveSnapshot functions produced correct layer properties and view zooms. <br />
I assume you have changed something in the progress bar class. Anything we can do here to make it play nicer with the main thread ?<br />
Thanks<br />
Thomas.</p>
]]>
        </description>
    </item>
    <item>
        <title>DRC with spike</title>
        <link>https://www.klayout.de/forum/discussion/2728/drc-with-spike</link>
        <pubDate>Thu, 22 May 2025 06:24:31 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>JSS</dc:creator>
        <guid isPermaLink="false">2728@/forum/discussions</guid>
        <description><![CDATA[<p>Hi everyone,</p>

<p>I have a question about the spike of polygon.<br />
<img src="https://klayout.de/forum/uploads/editor/8i/od8de3d64ba2.png" alt="" title="" /><br />
It can be deleted by Merge, but I am curious if it can be detected by DRC.<br />
Thanks for your help.</p>
]]>
        </description>
    </item>
    <item>
        <title>Ruby proper way to combine output and bbox.width judgement</title>
        <link>https://www.klayout.de/forum/discussion/2715/ruby-proper-way-to-combine-output-and-bbox-width-judgement</link>
        <pubDate>Thu, 15 May 2025 10:21:03 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>BigPanda</dc:creator>
        <guid isPermaLink="false">2715@/forum/discussions</guid>
        <description><![CDATA[<p><a rel="nofollow" href="https://www.klayout.de/forum/discussion/2703/ruby-drc-for-taper#latest" title="In this discussion">In this discussion</a>, we know how to realize the width of overlap part of taper. But I do not know how to write a proper script to do judgement to this bbox.width. As I understand, width checking is a function for <code>Layer</code> object. For a layer object, I can write it as:</p>

<pre><code>l1 = (1, 0)
l1.width(0.2.um).output('Minimum width', 'some tips here')
</code></pre>

<p>So it seems that width checking is automatically for the minimum checking. If I want to check the maximum length, what I find from tutorial is:</p>

<pre><code>l1 = (1, 0)
l1.drc(width &lt; 2.0um).output('Maximum width', 'some tips here')
</code></pre>

<p>Am I right?</p>

<p>=================================================================================<br />
For bbox.width, should I just write it as:</p>

<pre><code>l1 = (1, 0)
if l1.data.bbox.width &gt; 50.um
    l1.output('Maximum length', 'some tips here')
end
</code></pre>

<p>Is there a simplified way to realise this?</p>
]]>
        </description>
    </item>
    <item>
        <title>Can we have a DRegion class and a array DPolygon to Polygon constructor?</title>
        <link>https://www.klayout.de/forum/discussion/2714/can-we-have-a-dregion-class-and-a-array-dpolygon-to-polygon-constructor</link>
        <pubDate>Thu, 15 May 2025 09:23:55 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>BigPanda</dc:creator>
        <guid isPermaLink="false">2714@/forum/discussions</guid>
        <description><![CDATA[<p>Sorry for this discussion, I choose the wrong tag.</p>

<p>Recently, I am working with <code>pya</code> Module, and I find that it has <code>Path</code>, <code>DPath</code>, <code>Box</code>, <code>DBox</code> classes and so on, all of them are appeared in pairs. But it seems that there is no <code>DRegion</code> class. We can see from <a rel="nofollow" href="https://www.klayout.de/forum/discussion/2650/region-constructor#latest" title="https://klayout.de/forum/discussion/2650/region-constructor#latest">this dicussion</a> If we want to merge two polygons created by <code>DPolygon</code> constructor, it is not convenient because we need to transfer <code>DPolygon</code> to <code>Polygon</code>. If we want to transfer between them, normally we need to manually do unit conversion. Besides, as <a href="https://www.klayout.de/forum/profile/sekigawa" rel="nofollow">@sekigawa</a> said,  it seems that there is no constructor to transfer <code>array[] DPolygon</code> to <code>array[] Polygon</code>, which is also not convenient.</p>

<p>If we can have <code>DRegion</code> class, then there is another question, we know float and integer can be converted to each other. Why not combine <code>Box</code> and <code>DBox</code> classes, the other pairs are same. If this is possible, programming could be much easier I think.</p>
]]>
        </description>
    </item>
    <item>
        <title>Ruby DRC for taper</title>
        <link>https://www.klayout.de/forum/discussion/2703/ruby-drc-for-taper</link>
        <pubDate>Wed, 23 Apr 2025 07:51:07 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>BigPanda</dc:creator>
        <guid isPermaLink="false">2703@/forum/discussions</guid>
        <description><![CDATA[<p><a href="https://www.klayout.de/forum/profile/Matthias" rel="nofollow">@Matthias</a> Sorry, I did not make clear description before. I will modify my question. The orginal yellow polygon is not clear, so I changed it to black.</p>

<p>The problem I want to solve is like below:<br />
<img src="https://www.klayout.de/forum/uploads/editor/u6/1seaj14pahy9.png" alt="" title="" /></p>

<p>First, let us make some convention. <br />
1. Horizontal dimension: the width(length) of the taper. <br />
2. Vertical dimension: the height of the taper, and the low-height we call it height_l, the high-height we call it height_h.</p>

<p>Here, we see the layer 118/120, this is a transition layer, normally is used to mark the taper when its height lower than a threshold value. For example, here. the height_l = 0.04 um, the height_h = 0.2 um. The layer 118/120 marks the part height &lt; 0.1 um. The 171/0 layer is a waveguide layer.</p>

<p>Now, the overlap part of transition layer and waveguide layer is a small taper, and what I really to test is that:<br />
1.  The length of the this small taper. (Totally no idea)<br />
2. The length of four edges of this small taper could be known is better. (I saw some function to get this in Documents, I just start to learn about this part)<br />
3. The angle of this enclosed taper.(I saw some function to get this in Documents, I just start to learn about this part).</p>

<p>Hope you could give me some advice.</p>
]]>
        </description>
    </item>
    <item>
        <title>RDL Capture Pad</title>
        <link>https://www.klayout.de/forum/discussion/2708/rdl-capture-pad</link>
        <pubDate>Tue, 29 Apr 2025 02:15:33 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>안준용</dc:creator>
        <guid isPermaLink="false">2708@/forum/discussions</guid>
        <description><![CDATA[<p>Hello, I am a new user of Klayout DRC.</p>

<p>RDL Capture Pad is like the image below.<br />
I need to find the width (53.45um) of the blue layer in the section where the red layer exists. Is there a method that I can use?<br />
<img src="https://www.klayout.de/forum/uploads/editor/yi/7s8qbhqxm7mq.png" alt="" title="" /></p>
]]>
        </description>
    </item>
    <item>
        <title>TilingProcessor</title>
        <link>https://www.klayout.de/forum/discussion/2704/tilingprocessor</link>
        <pubDate>Fri, 25 Apr 2025 13:32:19 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>tomas2004</dc:creator>
        <guid isPermaLink="false">2704@/forum/discussions</guid>
        <description><![CDATA[<p>Hello Matthias,</p>

<p>I'm looking into the TilingProcessor feature and came along your example:</p>

<pre><code>layout = ... # the layout
cell = ... # the top cell's index
layout = ... # the input layer

class MyReceiver &lt; RBA::TileOutputReceiver
  def put(ix, iy, tile, obj, dbu, clip)
    puts "got area for tile #{ix+1},#{iy+1}: #{obj.to_s}"
  end
end

tp = RBA::TilingProcessor::new

# register the custom receiver
tp.output("my_receiver", MyReceiver::new)
tp.input("the_input", layout.begin_shapes(cell, layer))
tp.tile_size(100, 100)  # 100x100 um tile size
# The script clips the input at the tile and computes the (merged) area:
tp.queue("_output(my_receiver, (the_input &amp; _tile).area)")
tp.execute("Job description")
</code></pre>

<p>I would like to store the area values in an array instead of putting them to the console. I'm using a global variable to do this. Is this a good idea or is there a better way?</p>

<pre><code>$tile_areas = []
...
class MyReceiver &lt; TileOutputReceiver

          def put(ix, iy, tile, obj, dbu, clip)

            area = (obj*dbu**2).round(4)

            puts "Area for tile #{ix+1},#{iy+1}: #{area.to_s}"

            $tile_areas &lt;&lt; [ix+1, iy+1, area]

          end # def

end # class
</code></pre>

<p>Cheers,</p>

<p>Tomas</p>
]]>
        </description>
    </item>
    <item>
        <title>TilingProcessor part II: tiling array</title>
        <link>https://www.klayout.de/forum/discussion/2706/tilingprocessor-part-ii-tiling-array</link>
        <pubDate>Mon, 28 Apr 2025 11:45:24 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>tomas2004</dc:creator>
        <guid isPermaLink="false">2706@/forum/discussions</guid>
        <description><![CDATA[<p>Hi Matthias,</p>

<p>I'm looking further into the TilingProcessor feature using the attached gds file (using version 0.28.17). It's a simple layout with a 5x5 array of 200um tiles with a random square on layer 4/0 in each one of them. When running the script below, the area of the first tile is not 40000um^2 as I would expect but a bit less as shown in the output to the console.</p>

<pre><code>module MyMacro

      include RBA


      layout_view = Application.instance.main_window.current_view
      cell_view = layout_view.active_cellview
      layout = cell_view.layout
      viewed_cell = cell_view.cell
      dbu = layout.dbu

#--------- input --------------------------------------------------------------------------------------------

layer = "4/0"

tile_size = 200.0

#-------------------------------------------------------------------------------------------------------------

      puts "-"*120


      layer_number = layer.split("/")[0].to_i
      datatype_number = layer.split("/")[1].to_i


      input_layer_id = layout.layer(layer_number, datatype_number)


      class MyReceiver &lt; TileOutputReceiver

          def put(ix, iy, tile, obj, dbu, clip)

            input_area = (obj*dbu**2).round(8)

            puts "Input area of tile #{ix+1},#{iy+1} in um^2: #{input_area.to_s}\t\t\tTile Extents in um: #{tile.left*dbu}, #{tile.bottom*dbu}, #{tile.right*dbu}, #{tile.top*dbu}"

          end # def

      end # class


      tp = TilingProcessor.new


      # register the custom receiver

      tp.output("my_receiver", MyReceiver::new)

      tp.input("input_layer", layout.begin_shapes(viewed_cell, input_layer_id))

      tp.tile_size(tile_size, tile_size)

      # The script clips the input at the tile and computes the (merged) area:

      tp.queue("_output(my_receiver, (input_layer &amp; _tile).area)")

      tp.execute("Job description")


      puts "-"*120


end # Module
</code></pre>

<p>First few lines of console output:</p>

<p>Input area of tile 1,1 in um^2: 38311.960932            Tile Extents in um: -2.593, -5.924, 197.407, 194.076<br />
Input area of tile 1,2 in um^2: 24662.358144            Tile Extents in um: -2.593, 194.076, 197.407, 394.076<br />
Input area of tile 1,3 in um^2: 5551.7401           Tile Extents in um: -2.593, 394.076, 197.407, 594.076<br />
Input area of tile 1,4 in um^2: 23350.8961          Tile Extents in um: -2.593, 594.076, 197.407, 794.076<br />
Input area of tile 1,5 in um^2: 18559.702756            Tile Extents in um: -2.593, 794.076, 197.407, 994.076<br />
Input area of tile 2,1 in um^2: 4635.928864         Tile Extents in um: 197.407, -5.924, 397.407, 194.076<br />
...</p>

<p>The tiling array seems not to be centered around the original layout's center, but rather around the center of the bbox of the input layer 4/0.</p>

<p>When I force the tiling origin by adding:</p>

<p><code>tp.tile_origin(0.0, 0.0)</code></p>

<p>the result is as expected:</p>

<p>Input area of tile 1,1 in um^2: 40000.0                 Tile Extents in um: 0.0, 0.0, 200.0, 200.0<br />
Input area of tile 1,2 in um^2: 23492.919076            Tile Extents in um: 0.0, 200.0, 200.0, 400.0<br />
Input area of tile 1,3 in um^2: 5551.7401           Tile Extents in um: 0.0, 400.0, 200.0, 600.0<br />
Input area of tile 1,4 in um^2: 23350.8961          Tile Extents in um: 0.0, 600.0, 200.0, 800.0<br />
Input area of tile 1,5 in um^2: 18559.702756            Tile Extents in um: 0.0, 800.0, 200.0, 1000.0<br />
Input area of tile 2,1 in um^2: 4132.689796         Tile Extents in um: 200.0, 0.0, 400.0, 200.0<br />
...</p>

<p>Does that make sense?</p>

<p>Cheers,</p>

<p>Tomas</p>
]]>
        </description>
    </item>
    <item>
        <title>Obtain the angles of the skewed polygon to determine the shortest distance between conductors.</title>
        <link>https://www.klayout.de/forum/discussion/2699/obtain-the-angles-of-the-skewed-polygon-to-determine-the-shortest-distance-between-conductors</link>
        <pubDate>Tue, 22 Apr 2025 03:10:20 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>Luan</dc:creator>
        <guid isPermaLink="false">2699@/forum/discussions</guid>
        <description><![CDATA[<p>Hello,<br />
       I want to get the shortest distance between conductors and determine whether the conductors intersect, But for the skewed polygons, I can only get the the coordinates of the bottom-left and top-right corners. It might effect my judge for these boxes. I found the oblique polygons have eight points,  how can I read them and Is there a simpler method to determine the shortest distance between these boxes or polygons?</p>

<p>There is my Traversal function:</p>

<pre><code>[*(0..30)].each do |level|
   shape_count = 0
   box_count = 0
   # Traversal
   top_cell.shapes(level).each do |shape|
     if shape.is_box?
       bbox = shape.bbox
       shape_id = id_counter
      id_counter += 1
      shape_info = ShapeInfo.new(shape_id, [], [])
       shape_infos &lt;&lt; shape_info
  # Array used to save shape  
      rectangles &lt;&lt; { box: shape.box, layer: level }
      id_to_rectangle[shape_id] = { box: shape.box, layer: level }
       box_count += 1
      # test
       puts "box: #{shape_id}"
      count_shape += 1    # shape' counts
     elsif shape.is_polygon? || shape.is_path?
      # Deal with the polygon and path 
      bbox = shape.bbox
       shape_id = id_counter
       id_counter += 1
       shape_info = ShapeInfo.new(shape_id, [], [])
      shape_infos &lt;&lt; shape_info
  # Array used to save shape  
      rectangles &lt;&lt; { box: bbox, layer: level }
       id_to_rectangle[shape_id] = { box: bbox, layer: level }
       count_shape += 1
      # test
      puts "bbox: #{shape_id}"
     end
     shape_count += 1
   end

   if shape_count &gt; 0
    puts "Level #{level}: find #{shape_count} shapes， #{box_count} boxes。"
  else
     puts "Level #{level}: can't find any shape in this layer, step it."
   end
 end
</code></pre>

<p>Thinks，</p>

<p>Luan</p>
]]>
        </description>
    </item>
    <item>
        <title>Shapes object cannot be garbage collected</title>
        <link>https://www.klayout.de/forum/discussion/2687/shapes-object-cannot-be-garbage-collected</link>
        <pubDate>Mon, 31 Mar 2025 08:35:12 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>nice</dc:creator>
        <guid isPermaLink="false">2687@/forum/discussions</guid>
        <description><![CDATA[<p>I use</p>

<pre><code>shapes = layout.cell(cell_index).shapes(layer_info) 
</code></pre>

<p>and then call shapes.size() to get the number of shapes. This code runs well and quickly, but I have noticed that memory usage continues to rise. Using objgraph.show_most_common_types(), I found that the Shapes object remains in memory. Using objgraph.show_backrefs, I discovered that apart from gc.get_objects(), there are no other references. Similarly, I found that the q object inside for</p>

<pre><code> q in LayoutQuery("select cell_index, instances from cells *").each(layout)
</code></pre>

<p>has the same issue.I don't know how to resolve this issue, and I look forward to your response., thank you!</p>

<p>i sorry that it should be categorized under python scripting, but i made a mistake</p>
]]>
        </description>
    </item>
    <item>
        <title>xSection: Line of Sight, Negative Angle Etch etc</title>
        <link>https://www.klayout.de/forum/discussion/1632/xsection-line-of-sight-negative-angle-etch-etc</link>
        <pubDate>Wed, 26 Aug 2020 23:46:19 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>tnoradam</dc:creator>
        <guid isPermaLink="false">1632@/forum/discussions</guid>
        <description><![CDATA[<p>Hi Matthias,<br />
I managed to get deposit working with line-of-sight, and etch with negative taper, as well as with triangular undercut. I will post this one modified file when I have cleaned it up. I would like to ask for your help to combine line-of-sight with the regular :modes of :round / :octagon etc. We couldn't get that to work. Maybe you know a niftier way.</p>

<p>Also, it would be nice to have a command "RemoveFloating" or something like that. As an example, if nitride is etched out from under an oxide mask, and that oxide mask is narrow, then the oxide mask remains floating in air. In some cases, that is ok (when intentionally suspended in Y somewhere), but in other cases it would be great to have a cleanup command that can remove any [material1, material2, etc] not connected to other materials anymore.</p>

<p>Thanks.<br />
Thomas.</p>
]]>
        </description>
    </item>
    <item>
        <title>How do I use goto position in script for batch coordinate?</title>
        <link>https://www.klayout.de/forum/discussion/2674/how-do-i-use-goto-position-in-script-for-batch-coordinate</link>
        <pubDate>Fri, 14 Feb 2025 01:40:17 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>illyjustfine</dc:creator>
        <guid isPermaLink="false">2674@/forum/discussions</guid>
        <description><![CDATA[<p>I want to mark some coordinetes, how to make it work?</p>
]]>
        </description>
    </item>
    <item>
        <title>Select a cell and change layer</title>
        <link>https://www.klayout.de/forum/discussion/1225/select-a-cell-and-change-layer</link>
        <pubDate>Thu, 02 May 2019 08:47:45 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>gcusmai</dc:creator>
        <guid isPermaLink="false">1225@/forum/discussions</guid>
        <description><![CDATA[<p>Helo,</p>

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

<p>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).</p>

<p>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.</p>

<p>app = RBA::Application.instance</p>

<p>mw = app.main_window</p>

<p>layout_view = mw.current_view</p>

<p>layer_info = RBA::LayerInfo.new(101,1)<br />
layer_pn = RBA::LayerPropertiesNode::new</p>

<p>layer_pn.source = layer_info.to_s<br />
layout_view.insert_layer( layout_view.end_layers, layer_pn )</p>

<p>Thanks for support.</p>
]]>
        </description>
    </item>
    <item>
        <title>Finding pattern</title>
        <link>https://www.klayout.de/forum/discussion/2665/finding-pattern</link>
        <pubDate>Tue, 28 Jan 2025 19:34:50 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>IanD</dc:creator>
        <guid isPermaLink="false">2665@/forum/discussions</guid>
        <description><![CDATA[<p>I'm writing a DRC script to interpret gds files. I need to find a set of polygons in a layer with the exact same shape, or polygons with multiple holes of the same shape. I know that they repeat every 100um and are aligned ortho, but the actual shape may vary between files I need to process. Is there a way to test polygons against themselves independent of location, or a way to test if is_filled, or something like that?</p>
]]>
        </description>
    </item>
    <item>
        <title>Create a Hertel-Mehlhorn Partition as part of a DRC run</title>
        <link>https://www.klayout.de/forum/discussion/2660/create-a-hertel-mehlhorn-partition-as-part-of-a-drc-run</link>
        <pubDate>Tue, 21 Jan 2025 23:28:15 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>gyger</dc:creator>
        <guid isPermaLink="false">2660@/forum/discussions</guid>
        <description><![CDATA[<p>It seems convex partitions, is what I have to spent a little bit too much time in the recent days. The e-beam software, supports polygons as input now, were the shots are then nicely placed, but the polygons need to be convex. The initial results from the <a rel="nofollow" href="https://www.klayout.de/forum/discussion/2658/run-a-polygon-convex-decomposition-from-drc" title="previous thread">previous thread</a> were a start, but the partition was not utilizing the capability too well.</p>

<p>I then look a little bit around and found this library for partitioning polygons, and the results seemed promising (<a href="https://github.com/ivanfratric/polypartition" rel="nofollow">https://github.com/ivanfratric/polypartition</a>). Especially the Hertel-Mehlhorn algorithm seemed to work quite decent. I tried to implement a version in Ruby that is not yet smart enough to use the longest edge first (which seems to be heuristically the better one to merge), but it kind of works. Perhaps somebody finds it useful, or can improve it to be smarter or faster in the future.</p>

<pre><code>class DRC::DRCLayer
  def decompose_HM()
    result = RBA::Region.new 
    self.data.each do |p|
      if p.is_convex?
        result.insert(p)
        next
      end

      # Get initial triangulation
      current_region = RBA::Region::new(p)
      triangles = current_region.delaunay
      triangles_a = triangles.each.to_a

      changed = true
      while changed
        changed = false

        # Try each pair of triangles
        (0...triangles_a.length).each do |i|
          ((i+1)...triangles_a.length).each do |j|

            merged = RBA::Region.new
            merged.insert(triangles_a[i])
            merged.insert(triangles_a[j])
            # Perform merge
            merged.merge

              # Check if result is a single convex polygon
            if merged.count == 1 and merged[0].is_convex?
              # Update triangle list
              triangles_a.delete_at([i,j].max)
              triangles_a.delete_at([i,j].min)
              triangles_a.push(merged[0])

              changed = true
              break
            end
          end
          break if changed
        end
      end
      result.insert(triangles_a)
    end
    return DRC::DRCLayer::new(@engine, result)
  end
end
#

polys = polygons("Holes")
#polys.data = polys.data.delaunay
polys.decompose_HM.output(1006)
</code></pre>

<p>Also if Klayout ever supports some of the Hertel-Mehlhorn algorithms or even some optimal partition algorithm like Keil and Snoeyink,<br />
could be useful, but perhaps not very fast.</p>
]]>
        </description>
    </item>
    <item>
        <title>Extended with joined freezing software</title>
        <link>https://www.klayout.de/forum/discussion/2664/extended-with-joined-freezing-software</link>
        <pubDate>Fri, 24 Jan 2025 03:00:32 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>IanD</dc:creator>
        <guid isPermaLink="false">2664@/forum/discussions</guid>
        <description><![CDATA[<p>I'm using 'extended' to dilate a series of design geometries with the join option. With some of the designs KLayout freezes at this process. If I forgo the 'join' option, it works fine, but it's not what I prefer. I have tried breaking the process apart by doing individual polygons from the layer, still some polygon is killing it. Is there something I should be watching out for in my geometry that's causing an endless loop or something?</p>

<p>Due to this issue, I attempted to wrap the extended command with a Timeout, but KLayout still freezes at same point.</p>

<pre><code>begin
   Timeout.timeout(5) do
      buff = temp.edges.extended(0,0,fineDilation,0,true)
      print "."
    end
  rescue Timeout::Error
    buff = temp.edges.extended(0,0,fineDilation,0)
    print "|"
end
</code></pre>

<p>Can KLayout deal with timeouts? Or does this mean the extended process is freezing KLayout and not it's script interrupter that's watching for the timeout.</p>
]]>
        </description>
    </item>
    <item>
        <title>Folded Polygons</title>
        <link>https://www.klayout.de/forum/discussion/2663/folded-polygons</link>
        <pubDate>Thu, 23 Jan 2025 18:43:21 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>IanD</dc:creator>
        <guid isPermaLink="false">2663@/forum/discussions</guid>
        <description><![CDATA[<p>I'm running into an issue when subtracting one layer from another, the result ends up with a polygon that represents two separate areas connected by their corners. I need to grab the smaller areas, (which are artifacts to eliminate), but the two areas are treated as one. I tried using '.raw' in the subtraction, but it still comes out as a single polygon. Any suggestions to break apart the polygons at their touching corners, or how to stop the subtraction from merging at touching corners?</p>
]]>
        </description>
    </item>
    <item>
        <title>Ruby error on some platforms</title>
        <link>https://www.klayout.de/forum/discussion/2662/ruby-error-on-some-platforms</link>
        <pubDate>Thu, 23 Jan 2025 00:03:16 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>mrg</dc:creator>
        <guid isPermaLink="false">2662@/forum/discussions</guid>
        <description><![CDATA[<p>I get this error on some platforms when running LVS using the Sky130 PDK:</p>

<blockquote><div>
  <p>sh: line 1: pmap: command not found<br />
  ERROR: In /home/X/class/chip-tutorials/klayout/tech/sky130/pymacros/../lvs/sky130.lvs: undefined method <code>strip' for nil:NilClass ERROR: /home/X/class/chip-tutorials/klayout/tech/sky130/pymacros/run_lvs.lym:135: RuntimeError: NoMethodError: undefined method</code>strip' for nil:NilClass in Executable::execute<br />
    /home/X/class/chip-tutorials/klayout/tech/sky130/pymacros/../lvs/sky130.lvs:27:in <code>block in execute'   /nix/store/c4bdx4dja3h06xg1ksv3f51alp5a44li-ruby-3.1.5/lib/ruby/3.1.0/logger.rb:586:in</code>format_message'<br />
    /nix/store/c4bdx4dja3h06xg1ksv3f51alp5a44li-ruby-3.1.5/lib/ruby/3.1.0/logger.rb:476:in <code>add'   /nix/store/c4bdx4dja3h06xg1ksv3f51alp5a44li-ruby-3.1.5/lib/ruby/3.1.0/logger.rb:529:in</code>info'<br />
    /home/X/class/chip-tutorials/klayout/tech/sky130/pymacros/../lvs/sky130.lvs:34:in <code>execute'   :/built-in-macros/lvs_interpreters.lym:31:in</code>instance_eval'<br />
    :/built-in-macros/lvs_interpreters.lym:31:in `execute' in Macro.run<br />
    /home/X/class/chip-tutorials/klayout/tech/sky130/pymacros/run_lvs.lym:135</p>
</div></blockquote>

<p>I've confirmed that it works on:<br />
Ubuntu 20.04 with Ruby 2.7.1</p>

<p>But it fails on:<br />
Ubuntu 20.04 with Ruby 3.1.5 (inside Docker)<br />
MacOS Sequoia 15 with Ruby 2.6.10</p>

<p>I have a demo with an inverter.</p>
]]>
        </description>
    </item>
    <item>
        <title>Why after running script the layout layer all become invisible?</title>
        <link>https://www.klayout.de/forum/discussion/2654/why-after-running-script-the-layout-layer-all-become-invisible</link>
        <pubDate>Mon, 13 Jan 2025 08:10:03 +0000</pubDate>
        <category>Ruby Scripting</category>
        <dc:creator>illyjustfine</dc:creator>
        <guid isPermaLink="false">2654@/forum/discussions</guid>
        <description><![CDATA[<p>After I running this script below,all the layout pattern can't be seen.I wonder how to fix this.（Klayout version 0.29.10）</p>

<p>`tiles(3000.um)<br />
threads(8)</p>

<p>final_metal=input(110,0)<br />
die=input(71,0)</p>

<h6>#</h6>

<p>anser_list = Array.new()<br />
anser_list &lt;&lt; "Outer_SealRing"<br />
anser_list &lt;&lt; "Inner_SealRing"</p>

<p>seal_case=RBA::InputDialog::ask_item("need type", "SealRing type:",anser_list,1)<br />
if seal_case=="Outter_SealRing" then<br />
seal_ring_type=1<br />
end</p>

<p>if seal_case=="Inner_SealRing" then<br />
seal_ring_type=2<br />
end</p>

<h6>#</h6>

<p>tone_list = Array.new()<br />
tone_list &lt;&lt; "pTone"<br />
tone_list&lt;&lt; "nTone"</p>

<p>tone_case=RBA::InputDialog::ask_item("input final metal", "tone type:",tone_list,1)<br />
if tone_case=="pTone" then</p>

<p>end</p>

<p>if tone_case=="nTone" then<br />
final_metal=die-final_metal<br />
end</p>

<h6>#</h6>

<p>flat<br />
sealring_gap=15</p>

<p>seal_ring=final_metal.outside(die.sized(-sealring_gap*10.um))<br />
seal_ring.holes.merged(seal_ring_type).output(111,0)`</p>
]]>
        </description>
    </item>
   </channel>
</rss>
