"New Panel" creates a new tab but without a layout loaded. That is not what you need.
All edit commands like "new layout" or "new cell" create new objects but don't import anything.
What you can do is to open the four GDS files in separate tabs. Then you create a new layout using "New layout" and copy the four cells of the four layouts into the new one. To do so, select the tab of layout "A", select the top cell in the cell tree and choose "Copy" from the cell tree's context menu (right mouse button). Then go to the new layout's tab and paste the cell into this by choosing "Paste" from the cell list's context menu.
Proceed the same way with the other cells and finally you'll have all four cells in the new layout. You can then combine them into a single layout by creating instances of these cells in the new layout's top cell.
That depends somewhat of the merge functionality. The feature available in "File->Import->Other File Into Current" is somewhat elaborate and is not easy to use inside a Ruby script.
A simple merge however can be achieved with that script:
# merge_files.rb
#
# Merges two files into one
#
# Run this script with
# klayout -rd file1=first_file.gds -rd file2=second_file.gds -rd output=output_file.gds -z -r merge_files.rb
#
# (Note: -z puts KLayout into non-GUI mode)
#
# WARNING: this implementation merges the contents of all cells with identical names
# unless the cells are renamed (see comments)
# Read the first layout
layout = RBA::Layout.new
lmap = layout.read($file1)
# read the second file which basically performs the merge
load_layout_options = RBA::LoadLayoutOptions.new
load_layout_options.set_layer_map(lmap, true)
layout.read($file2, load_layout_options)
layout.write($output)
Please note the warning: this script will merge cells named identically in both files which may result in severe distortions of the layout. If you want to prevent this, you can use a modified form of the script which prefixes the cell names of the layouts:
# merge_files.rb
#
# Merges two files into one
#
# Run this script with
# klayout -rd file1=first_file.gds -rd file2=second_file.gds -rd output=output_file.gds -z -r merge_files.rb
#
# All cells of file1 are prefixed with "A", all cells of file2 with "B".
#
# (Note: -z puts KLayout into non-GUI mode)
# Read the first layout
layout = RBA::Layout.new
lmap = layout.read($file1)
# store and take away the cell names of all cells read so far
# (by setting the cell name to "" the cells basically become invisible for
# the following read)
cell_names = { }
(0..(layout.cells-1)).each do |ci|
cell_names[ci] = layout.cell_name(ci)
layout.rename_cell(ci, "") # this prevents a name clash on the next read
end
# read the second file which basically performs the merge
load_layout_options = RBA::LoadLayoutOptions.new
load_layout_options.set_layer_map(lmap, true)
layout.read($file2, load_layout_options)
# rename the cells by using prefix "A" for layout 1 and "B" for layout 2
(0..(layout.cells-1)).each do |ci|
if cell_names[ci]
layout.rename_cell(ci, "A" + cell_names[ci])
else
layout.rename_cell(ci, "B" + layout.cell_name(ci))
end
end
layout.write($output)
Please note that both versions of the script do not deliver reasonable results if the database units of the files differ.
I used your first script to merge some dummy pattern gds files and it works like a charm.
Compared with running a SKILL script in Virtuoso, this script saves me time.
However, there is one problem. The script seems to work with small gds files. If each gds file is bigger than 20+MB, I got error message:
ERROR: Ruby error: 'Operation cancelled' (RuntimeError)
./merge_files.rb: in 'write'
I tried to set some options in SaveLayoutOptions in layout.write but not working.
(e.g. gds2_allow_big_records=true and gds2_allow_multi_xy_records=true)
Could you give me some advice? I can send you the gds files if it helps to clarify the issue.
Thanks and Best Regards,
Allen
when merging two slightly bigger gds files. Big means the combined gds
you're right. Apparently KLayout tries to bring up the progress bar and since that fails, it cancels the operation.
I'll try to fix that in the next version. There is a simple workaround: just don't use the -z option. In that case, KLayout shows the user interface and the progress bar is displayed. Hence, the script does not abort.
Thanks for solving my question! It works well without -z option.
One more question: can I extend the above script to merge three files or more?
I added "layout.read($file3, load_layout_options)" in the script and run it. The error message is "internal error: /root/klayout-0.21.15/src/dblayout.cc:1365 m_layer_states[index]== Free was not true."
Is there a limitation of the script? Just curious.
there is no general limitation, but the code adaptations required are somewhat more elaborate. First you have to save the layer map after each load (failing to do so gives the error message you observed). Then you need to reset the cell names before each load to avoid the name clashes.
Here is the generic form of the script:
# merge_n_files.rb
#
# Merges multiple files into one
#
# Run this script with
# klayout -rd files=first_file.gds,second_file.gds,third_file.gds -rd prefixes=A,B,C rd output=output_file.gds -r merge_n_files.rb
#
files = $files.split(/,/)
prefixes = $prefixes.split(/,/)
lmap = nil
layout = RBA::Layout.new
cell_name_maps = []
files.each do |file|
# read the file which basically performs the merge
load_layout_options = RBA::LoadLayoutOptions.new
lmap && load_layout_options.set_layer_map(lmap, true)
lmap = layout.read(file, load_layout_options)
# store and take away the cell names of all cells read so far
# (by setting the cell name to "" the cells basically become invisible for
# the following read)
cell_name_map = { }
(0..(layout.cells-1)).each do |ci|
if !layout.cell_name(ci).empty?
cell_name_map[ci] = layout.cell_name(ci)
layout.rename_cell(ci, "") # this prevents a name clash on the next read
end
end
cell_name_maps.push(cell_name_map)
end
# rename the cells by using the given prefixes for the different layouts
(0..(layout.cells-1)).each do |ci|
cell_name_maps.each_with_index do |m,i|
if m[ci]
layout.rename_cell(ci, prefixes[i] + m[ci])
end
end
end
layout.write($output)
Comments
"New Panel" creates a new tab but without a layout loaded. That is not what you need.
All edit commands like "new layout" or "new cell" create new objects but don't import anything.
What you can do is to open the four GDS files in separate tabs. Then you create a new layout using "New layout" and copy the four cells of the four layouts into the new one. To do so, select the tab of layout "A", select the top cell in the cell tree and choose "Copy" from the cell tree's context menu (right mouse button). Then go to the new layout's tab and paste the cell into this by choosing "Paste" from the cell list's context menu.
Proceed the same way with the other cells and finally you'll have all four cells in the new layout. You can then combine them into a single layout by creating instances of these cells in the new layout's top cell.
Best regards,
Matthias
Is it possible to use a ruby script to merge several GDS and stream out into one GDS?
Thanks and BR,
Allen
Hi Allen,
That depends somewhat of the merge functionality. The feature available in "File->Import->Other File Into Current" is somewhat elaborate and is not easy to use inside a Ruby script.
A simple merge however can be achieved with that script:
Please note the warning: this script will merge cells named identically in both files which may result in severe distortions of the layout. If you want to prevent this, you can use a modified form of the script which prefixes the cell names of the layouts:
Please note that both versions of the script do not deliver reasonable results if the database units of the files differ.
Hopefully that helps.
Best regards,
Matthias
Thanks a lot for your response and help!
I used your first script to merge some dummy pattern gds files and it works like a charm.
Compared with running a SKILL script in Virtuoso, this script saves me time.
However, there is one problem. The script seems to work with small gds files. If each gds file is bigger than 20+MB, I got error message:
ERROR: Ruby error: 'Operation cancelled' (RuntimeError)
./merge_files.rb: in 'write'
I tried to set some options in SaveLayoutOptions in layout.write but not working.
(e.g. gds2_allow_big_records=true and gds2_allow_multi_xy_records=true)
Could you give me some advice? I can send you the gds files if it helps to clarify the issue.
Thanks and Best Regards,
Allen
when merging two slightly bigger gds files. Big means the combined gds
Hi Allen,
you're right. Apparently KLayout tries to bring up the progress bar and since that fails, it cancels the operation.
I'll try to fix that in the next version. There is a simple workaround: just don't use the -z option. In that case, KLayout shows the user interface and the progress bar is displayed. Hence, the script does not abort.
Thanks for the hint and best regards,
Matthias
Thanks for solving my question! It works well without -z option.
One more question: can I extend the above script to merge three files or more?
I added "layout.read($file3, load_layout_options)" in the script and run it. The error message is "internal error: /root/klayout-0.21.15/src/dblayout.cc:1365 m_layer_states[index]== Free was not true."
Is there a limitation of the script? Just curious.
Thanks and best regards,
Allen
Hi Allen,
there is no general limitation, but the code adaptations required are somewhat more elaborate. First you have to save the layer map after each load (failing to do so gives the error message you observed). Then you need to reset the cell names before each load to avoid the name clashes.
Here is the generic form of the script:
Best regards,
Matthias
The script works well. Thanks for providing the awesome tool and script!
Best Regards,
Allen