Goto position and Snapshot

edited July 2013 in Ruby Scripting
Hi Matthias,

Is there a sample ruby code that describe how to do the action "Goto Position" and then "Snapshot / Screenshot to a PNG file" just like in window mode ?

We hope to get the layout screen with multiple coordinates in batch mode however have no idea how to do that, could you please give us a hint ? thank you so much~

Best Regards,
--
chhung

Comments

  • edited July 2013

    Hi chhung,

    this is code which does that:

    # input file
    input_file = "t10.gds"
    
    # width, height of image
    width = 500
    height = 500
    
    # rectangle to draw (left, bottom, right, top in micron coordinates)
    rect_drawn = RBA::DBox::new(-100.0, -200.0, 100.0, 200.0)
    
    # output file
    output_file = "t10.png"
    
    # load the layout
    mw = RBA::Application::instance.main_window
    mw.load_layout(input_file, 0)
    view = mw.current_view
    
    # select full hierarchy and the rectangle to draw
    view.max_hier
    view.zoom_box(rect_drawn)
    
    # save image
    view.save_image("#{output_file}", width, height)
    

    Please replace the values by yours. I hope the code is documented well enough, so you're able to adapt it to your needs.

    Regards,

    Matthias

  • edited July 2013

    Hi Matthias,

    I tried to run the RBA code and it responsed the error:

    *** ERROR: ./test.rba:9: Ruby error: 'uninitialized constant RBA::DRect' (NameError)
      ./test.rba:9 (class NameError)
    

    And is it possible to run the code in non-GUI mode ?

    Best Regards,

    chhung

  • edited November -1

    Hi,

    Sorry, it should say "DBox". I edited the code.

    You can run "klayout -z ..." with the script, but not with -zz. In the latter mode there is no view object and KLayout is a pure layout processor without any graphics.

    Regards,

    Matthias

  • edited November -1

    Hi Matthias,

    I tried the new code and it works fine~ :)

    Thank you so much~

    Best Regards,

    chhung

  • edited November -1
    Hi, Matthias,

    I have a question about the batch sanpshot.
    Ex, there are total 10 layers of the gds (1/0,2/0,3/0,4/0, ....,10/0),
    I only want to show 1/0, 3/0 and 10/0 layers of the images.
    How could I do that with this batch code?

    Thank you.

    Regards,
    Canny
  • edited November -1

    Hi Canny,

    the easiest solution is to prepare a .lyp file with the layer properties (colors, stipples, styles and
    the layers you want to show) and load the layer properties:

    # load the layout
    mw = RBA::Application::instance.main_window
    mw.load_layout(input_file, 0)
    view = mw.current_view
    
    # load the layer properties
    view.load_layer_props(the_path_to_your_lyp_file, false)
    
    ...
    

    Regards,

    Matthias

  • edited November -1
    Hi, Matthias,

    Thanks a lot, it does save lot of time of mine.

    Regards,
    Canny
  • edited November -1
    Hi, Matthias,

    I have another question, when I use the above script

    # script start
    mw = RBA::Application::instance.main_window
    mw.load_layout(input_file, 0)
    view = mw.current_view
    #--script end

    It always shows the top cell of the input file.
    If I want to assign coordinates are according to the other cell of the input file.
    How could I modify the script?

    Thank you.

    Regards,
    Canny
  • edited November -1

    Hi Canny,

    you mean "how to show another cell"? You can do that this way (in this example the name of the cell to show is "MY_CELL":

    cell = view.active_cellview.layout.cell_by_name("MY_CELL")
    view.select_cell(cell, view.active_cellview_index)
    

    Matthias

  • edited November -1
    Hi, Matthias,

    Yes, it is what I need.
    Thank you.

    Regards,
    Canny
  • edited November -1
    Hi,

    I want to add a function that goes to a specific location within the gdsii/oasis and create a view with a specific magnification. Then I want to take a snapshot such that the pixel width/height is identical if I then perform another goto position/mag and take another screendump. I want to do that repeatedly throughout the gdsii. I tried to find an analog to the display-goto-position (CTRL-G) but cannot find it yet.

    Thanks,
    Chris
  • edited June 2015

    Chris,

    Here is some code that reproduces display-goto-position (Ctrl-G) with minor changes. I wrote it before I knew that display-goto-position existed ;)

    Hopefully you can modify for your purposes, e.g. it sounds like you need to put it in a loop of some kind, and you need to add the screenshot function (there are examples on klayout.de to do that).

    When you have a finished code, please share it here.

    Thanks,

    David

    ## Zooms viewing window to a certain x,y location with optional magnification
    
    zoom_default = 500.0 # um
    
    include RBA
    app = Application.instance
    mw = app.main_window
    lv = mw.current_view
    raise "No view selected" if lv.nil?
    ly = lv.active_cellview.layout
    dbu = ly.dbu
    
    # Get current "x,y : zoom"
    #p curr_x = ... # There is no way to get this using the API??
    #p curr_y = ... # There is no way to get this using the API??
    #p curr_trans = lv.viewport_trans
    #p curr_zoom = lv.viewport_width
    curr_x,curr_y,curr_zoom = 0,0,100 # Temporary, until the above lines work
    
    input = InputDialog.ask_string(
      "Zoom",
      "Move to x,y location (with optional horiz extent 'zoom') \n
      x,y : zoom", 
      "#{curr_x},#{curr_y} : #{curr_zoom}")
    
    # Error checking
    input = /(\d+(.)?\d*( )?,( )?\d+(.)?\d*( )?:( )?\d+(.)?\d*|\d+(.)?\d*( )?,( )?\d+(.)?\d*)/.match(input).to_s # This regex is not perfect, but catches most cases
    if input.empty?
      raise "Incorrect format. Use 12.3,45 : 100 or 12.3,45 for example."
    else
    
      # Remove spaces
      input.gsub!(' ','')
    
      # Split string
      xy,zoom = input.split(':')
      x,y = xy.split(',')
    
      # Convert to float
      x = x.to_f
      y = y.to_f
      zoom = zoom.to_f
      if zoom < 1e-4 # If zoom is zero, it's invalid, so use the default zoom
        zoom = zoom_default
      end
    
      if (x.is_a? Numeric) && (y.is_a? Numeric)
        left  = x - zoom/2.0
        bott  = y - zoom/2.0
        right = x + zoom/2.0
        top   = y + zoom/2.0
        p [left,bott,right,top]
        zoom_box = DBox.new(left,bott,right,top)
        lv.zoom_box(zoom_box)
      end
    
    end
    
  • edited November -1

    Thanks very much again, David!

    Plus here is the line for writing the screenshot:

    # Arguments: file name, image width and height (both in pixels)
    # The format will be PNG.
    lv.save_image("image_file.png", 640, 480)
    

    Matthias

  • edited November -1
    Hi Matthias,

    Can we do this in pure script mode (-zz) without GUI ?

    Thanks
  • edited January 2017

    Hi klfun,

    no, you can't (currently). The drawing feature is too tighly connected to the Windowing system.

    You can however run any program headless with a dummy display using "Xvfb":

    xvfb-run ./klayout -z -r your_script.rb
    

    Regards,

    Matthias

  • edited September 2020

    regarding David's script above.
    I think two lines can be changed as below

    #p curr_x = ... # There is no way to get this using the API??** --> curr_x = lv.box.center.x**
    #p curr_y = ... # There is no way to get this using the API??**--> curr_y = lv.box.center.y**
    
Sign In or Register to comment.