Layer properties (name, color, ...) from the layer index

edited July 2013 in Ruby Scripting
Hi Matthias,

How to get the layer properties (name, color, ...) from the layer index ?

Thanks, Best regards,

Laurent

Comments

  • edited November -1

    Hi Laurent,

    basically layer index and layer properties are two different items - one is the related to the layout database and one to the view. To find the layer properties for a layer index, you'll need the LayerPropertiesIterator object and the following code

    layer_index = ...    # The layer index
    cv_index = ...       # The cellview index for which you are looking up the layer
    lv = ...             # The LayoutView object 
    
    lp_found = nil
    iter = lv.begin_layers
    while !iter.at_end?
      lp = iter.current
      if lp.cv_index == cv_index && lp.layer_index == layer_index
        lp_found = lp 
      end
      iter.next
    end
    
    # lp_found gives the LayerPropertiesNode object with the display properties or
    # nil if the layer is not in the list
    

    Regards,

    Matthias

  • edited March 2015

    Hi Matthias,

    Should this code still work in version 0.23.10? With this code, I get a undefined method 'cv_index' for #<RBA::LayerPropertiesNode:0x0000000712f704> error. Here is the code:

    def self.get_layer_name2(layer_index)
      lv = Application::instance.main_window.current_view
      cv_index = lv.active_cellview_index
    
      iter = lv.begin_layers
      while !iter.at_end?
        lp = iter.current
        if lp.cv_index == cv_index && lp.layer_index == layer_index
          return lp 
        end
        iter.next
      end
      return nil
    end
    

    Any help would be appreciated.

    Thanks, FriendFX

  • edited March 2015

    Use

    lp.cellview
    

    instead of

    lp.cv_index
    

    The .cellview method belongs to class LayerProperties, for which LayerPropertiesNode is a child. I just tried it in the following code and it seems to work.

    include RBA
    app = Application.instance
    mw  = app.main_window
    lv  = mw.current_view
    cv  = lv.active_cellview
    cv_index = cv.cell_index
    ly  = cv.layout
    dbu = ly.dbu
    
    layer_index = 0    # The layer index
    
    lp_found = nil
    iter = lv.begin_layers
    while !iter.at_end?
      lp = iter.current
      if lp.cellview == cv_index && lp.layer_index == layer_index
        lp_found = lp 
      end
      iter.next
    end
    
    if lp_found.nil?
      p "Not found"
    else
      p "Found. Has dither pattern index = #{lp_found.dither_pattern}"
    end
    

    David

  • edited November -1

    Hi David,

    thanks again :-)

    I wonder whether the code above ever worked. Maybe it was a typo and nobody noticed. "cellview" is the right method, not "cv_index".

    Matthias

  • edited November -1
    Yes, I'm making your job too easy, you should give me a raise!

    (Of course that was a joke -- nobody's being paid to do this which makes Matthias's software all the more impressive!)
  • edited November -1

    Hi again.

    Thanks for your help David, I have changed your code slightly (and removed a small error where you had cv_index = cv.cell_index) to create a get_layer_name function as follows:

    def self.get_layer_name(layer_index)
      lv = Application::instance.main_window.current_view
      cv  = lv.active_cellview
      cv_index = lv.active_cellview_index
    
      iter = lv.begin_layers
      while !iter.at_end?
        lp = iter.current
        if lp.cellview == cv_index && lp.layer_index == layer_index
          return lp.name
        end
        iter.next
      end    
      return "<unknown layer #{layer_index}>"
    end
    

    This works fine now for primitive geometry (boxes, polygons etc.) but I have trouble getting it to work with layer parameters on PCells - is the layer member of a PCellParameterDeclaration object the same as the layer_index in my code above?

    Do illustrate my problem, here is the rest of this module's code:

    class MyObserver < Observer
      def signal 
        mw = RBA::Application::instance.main_window
        lv = mw.current_view
    
        info = ""
    
        lv.each_object_selected do |sel|
          if !sel.is_cell_inst?
            layer_index = sel.layer
            layer_name = LayerTest2::get_layer_name(layer_index)
            info = "layer index #{layer_index} = #{layer_name}\n"
            info += "Press Cancel to un-register observer."
          elsif sel.is_cell_inst?
    
            inst = sel.inst
            cell = inst.cell
            info += "#{cell.basic_name}:\n"
            if cell.is_pcell_variant?(inst)
              pcell_declaration = cell.pcell_declaration(inst)
              pcell_declaration.get_parameters.each_with_index do |pd, pd_idx|
                if !pd.hidden? || !pd.readonly?
                  info += ("         #{pd.name}") # - #{pd.description}
                  value = cell.pcell_parameters(inst)[pd_idx]
                  case pd.type
                  when RBA::PCellParameterDeclaration::TypeLayer
                    info += " = #{LayerTest2::get_layer_name(value.layer)}\n"
                  else
                    begin
                      info += " = #{value}\n"
                    rescue
                      info += "<unsupported type>\n"
                    end
                  end
                end
              end
            end
            info += "\n"
    
          end
    
          result = RBA::QMessageBox::information(mw, "Layer", info, RBA::QMessageBox::Ok.to_i | RBA::QMessageBox::Cancel.to_i)
          if result == RBA::QMessageBox::Cancel.to_i
            lv.remove_selection_changed_observer(self)
          end
    
        end
    
      end
    end
    observer = MyObserver::new
    Application::instance.main_window.current_view.add_selection_changed_observer(observer)  
    

    This opens a dialog showing either the layer_index and the layer name (if a primitive object is selected) or a list of parameters of a selected PCell instance. For some reason, the layer names returned by my get_layer_name function are not always correct when I select PCell instances, making me wonder if I am getting the right index there.

    My test layout includes just a bunch of polygons, rectangles and paths for the "primitive" case, as well as some BASIC.CIRCLE PCell instances (using different layer settings) for the "complex" case.

  • edited November -1

    Hi friendfx,

    sorry for the late reply ... I'm simply too overloaded currently.

    For PCell's the concept of a layer is a very different one. A PCell parameter has to be something abstract, since it's valid across instances of an layout.

    Layer indexes are assigned by the system incrementally. Whenever the program requires a new layer, it will use the next index available. The actual stream representation of the layer (GDS/OASIS layer/datatype, CIF/DXF/LEF layer name) is stored as annotated information in RBA::LayerInfo objects. When you work with layers in the layer, the layer index is used to uniquely identify the layer and in order to get the layer info, you can use RBA::Layout::get_info(layer_index), which renders a RBA::LayerInfo object.

    A PCell parameter, being an abstract entity without knowledge about the actual layout it's used in, stores a RBA::LayerInfo object. RBA::LayerInfo.layer gives the GDS layer number which only by chance is coincident with the layer index. If you need the layer index you can find the layer for a given RBA::LayerInfo object by using RBA::Layout::find_layer:

    # instead of value.layer, use:
    cell.layout.find_layer(value)
    

    (disclaimer: untested)

    Matthias

  • edited April 2015

    Hi Matthias,

    Thanks a lot for your continued support and this great software! Apparently I keep getting confused about the manifold relationships between GDS layer numbers, layer names in .lyp files and layer indices used in the layout database. I guess I should have realised that the documentation already mentions that the "value" of a PCell parameter of TypeLayer is a LayerInfo object...

    Using your advice, I changed the following line in my code from above,

    info += " = #{LayerTest2::get_layer_name(value.layer)}\n"
    

    to the following:

    layer_index = cell.layout.find_layer(value)
    info += " = #{LayerTest2::get_layer_name(layer_index)}\n"
    

    Which works perfectly now!

Sign In or Register to comment.