Class: Gdsii::Structure

Inherits:
Group
  • Object
show all
Includes:
Access::GdsiiTime
Defined in:
lib/gdsii/structure.rb

Overview

Represents a GDSII Structure.

Instance Attribute Summary

Attributes inherited from Group

#records

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Access::GdsiiTime

#build_time

Methods inherited from Group

bnf_key, bnf_key=, bnf_spec, bnf_spec=, #configure, #validate, #write

Methods included from Read

#read

Constructor Details

#initialize(name = nil) {|_self| ... } ⇒ Structure

Creates a Structure object. Various GDSII Elements are added to a structure such as a Boundary, Path, SRef, ARef, Text, Node, and Box.

str_sub = Structure.new('sub')
str_top = Structure.new('top')
str_top.add SRef.new(str_sub)
str_top.add Boundary.new(1, 0, [0,0, 0,10, 10,10, 10,0, 0,0])

Yields:

  • (_self)

Yield Parameters:



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/gdsii/structure.rb', line 45

def initialize(name=nil)
  # Create the record grouping
  super()
  @records[Elements] = Elements.new
  @records[GRT_ENDSTR] = Record.new(GRT_ENDSTR)

  # set the name
  self.name = name unless name.nil?

  # Set create/modify time to the current time
  now = Time.now
  self.create_time = now
  self.modify_time = now

  yield self if block_given?
end

Class Method Details

.read_each(file) ⇒ Object

Reads each Structure and its Elements from the given file handle. Each Structure is yielded after the entire Structure is read from the file. Compare this with Structure#read_each_header which might be more efficient, more streamlined, and consume less memory.

The Library#read_header method must be called as a prerequisite (the file handle must be at a BGNSTR record).

File.open(file_name, 'rb') do |file|
  Library.read_header(file) do |lib|
    Structure.read_each(file) do |struct|
      puts "#{struct.name} has #{struct.elements.length} elements"
    end
  end
end


203
204
205
206
207
# File 'lib/gdsii/structure.rb', line 203

def Structure.read_each(file)
  while (Record.peek(file).type == GRT_BGNSTR) do
    yield Structure.read(file)
  end
end

.read_each_header(file) ⇒ Object

Reads the Structure header records from a file handle but without reading any Element records. The resulting Structure element is yielded. This is useful for using the high-level GDSII access methods as a stream file is being read in.

Prior to using this method, the file position must be at the first structure definition (i.e. after the Library header). The best method to do this is to call Library#read_header first.

Also, you MUST advance the file position to the next structure record header (BGNSTR) either with Structure#seek_next or Structure#read_each_element within the code block. Otherwise the file pointer will not be advanced properly and only the first Structure will be yielded.

File.open(file_name, 'rb') do |file|
  Library.read_header(file) do |lib|
    Structure.read_each_header(file) do |struct|
      if struct.name == 'TOP'
        # Show all elements in structure "TOP"
        puts "Processing structure #{struct.name}"
        Element.read_each(file) do |element|
          puts "--> Element: #{element.class}"
        end
      else
        # Skip past elements in other blocks
        puts "Ignoring structure #{struct.name}"
        Structure.seek_next(file)
      end
    end
  end
end


243
244
245
246
247
# File 'lib/gdsii/structure.rb', line 243

def Structure.read_each_header(file)
  while (Record.peek(file).type == GRT_BGNSTR) do
    yield Structure.read_header(file)
  end
end

.read_header(file) ⇒ Object

Reads records related to a Structure header from the given file handle. It is assumed that the file position is already at BGNSTR (likely after Library#read_header). The structure is yielded (if desired) and returned. The iterative version of this method is likely preferable in most cases (Structure#read_each_header).



179
180
181
182
183
184
# File 'lib/gdsii/structure.rb', line 179

def Structure.read_header(file)
  Structure.read(file, nil, nil, :before_group) {|struct|
    yield struct if block_given?
    break struct
  }
end

.seek_next(file) ⇒ Object

Reads from the given file handle until a ENDSTR record is met (presumably to a BGNSTR or ENDLIB record. This effectively “skips” past all elements within a structure and prepares the file handle to read the next structure in the file (or ENDLIB if at the end of the GDSII library). See Structure#read_each_header for an example. The new file position is returned.

Compare this with Element#read_each which accomplishes the same thing but instead yields each element as it is read from the file.



260
261
262
263
264
265
# File 'lib/gdsii/structure.rb', line 260

def Structure.seek_next(file)
  Record.read_each(file) do |record|
    break file.pos if record.is_endstr?
  end
  nil
end

Instance Method Details

#add(*args) ⇒ Object

Shortcut for Elements#add. For example, instead of:

struct = Structure.new('test')
struct.elements.add Text(1, 0, [0,0], 'hello')

It could be simply:

struct.add Text(1, 0, [0,0], 'hello')


77
# File 'lib/gdsii/structure.rb', line 77

def add(*args); elements.add(*args); end

#bgnstrObject

Get the bgnstr number (returns Fixnum). This holds the create/modify time stamp for the structure. It is probably easier to not access this directly but to use #create_time and #modify_time instead.



132
# File 'lib/gdsii/structure.rb', line 132

def bgnstr() @records.get_data(GRT_BGNSTR); end

#bgnstr=(val) ⇒ Object

Set the bgnstr number. The value is a Fixnum representation of the create/modify time stamp for the structure. It is probably easier to not access this directly but to use #create_time= and #modify_time= instead.



140
# File 'lib/gdsii/structure.rb', line 140

def bgnstr=(val) @records.set(GRT_BGNSTR, val); end

#bgnstr_recordObject

Get the bgnstr record (returns Record).



125
# File 'lib/gdsii/structure.rb', line 125

def bgnstr_record() @records.get(GRT_BGNSTR); end

#create_timeObject

Returns the create time for this structure (returns Time)



155
# File 'lib/gdsii/structure.rb', line 155

def create_time(); @create_time; end

#create_time=(time) ⇒ Object

Accepts a Time object and sets the create time for the structure.

struct.create_time = Time.now


147
148
149
150
# File 'lib/gdsii/structure.rb', line 147

def create_time=(time)
  @create_time = time
  update_times
end

#elementsObject

Access to the Elements object. See Elements for a listing of methods.



65
# File 'lib/gdsii/structure.rb', line 65

def elements(); @records.get(Elements); end

#modify_timeObject

Returns the modify time for this structure (returns Time)



170
# File 'lib/gdsii/structure.rb', line 170

def modify_time(); @modify_time; end

#modify_time=(time) ⇒ Object

Accepts a Time object and sets the modify time for the structure.

struct.modify_time = Time.now


162
163
164
165
# File 'lib/gdsii/structure.rb', line 162

def modify_time=(time)
  @modify_time = time
  update_times
end

#nameObject

Get the Structure name (returns String).



98
# File 'lib/gdsii/structure.rb', line 98

def name() @records.get_data(GRT_STRNAME); end

#name=(val) ⇒ Object

Set the Structure name.



103
# File 'lib/gdsii/structure.rb', line 103

def name=(val) @records.set(GRT_STRNAME, val); end

#name_recordObject

Get the Structure STRNAME record (returns Record).



93
# File 'lib/gdsii/structure.rb', line 93

def name_record() @records.get(GRT_STRNAME); end

#remove(*args) ⇒ Object

Shortcut for Elements#remove. For example, instead of:

struct.elements.remove {|e| e.class == Gdsii::Text}

It could be simply:

struct.remove {|e| e.class == Gdsii::Text}


88
# File 'lib/gdsii/structure.rb', line 88

def remove(*args); elements.remove(*args); end

#strclassObject

Get the strclass bitarray number (returns Fixnum).



113
# File 'lib/gdsii/structure.rb', line 113

def strclass() @records.get_data(GRT_STRCLASS); end

#strclass=(val) ⇒ Object

Set the strclass bitarray number. According to the GDSII specification, this is only to be used by Calma - otherwise it should be omitted or set to 0. It is probably a good idea to not touch this property.



120
# File 'lib/gdsii/structure.rb', line 120

def strclass=(val) @records.set(GRT_STRCLASS, val); end

#strclass_recordObject

Get the strclass record (returns Record).



108
# File 'lib/gdsii/structure.rb', line 108

def strclass_record() @records.get(GRT_STRCLASS); end

Writes only the Structure footer (just ENDSTR record) to file. To be used with #write_header.



299
300
301
# File 'lib/gdsii/structure.rb', line 299

def write_footer(file)
  Record.new(GRT_ENDSTR).write(file)
end

#write_header(file) ⇒ Object

Writes only the header portion of the Structure to a file (no elements). This is useful when streamlined writing is desired (for better performance or when writing GDSII as another GDSII is being read). Be sure to either:

  1. Call #write_footer after writing the header and any Element

objects. Also be sure to wrap this around Library#write_header and Library#write_footer; Or

  1. Pass a block whereupon the footer will automatically be added after

the block is processed.

See Library#write_header for an example.



281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/gdsii/structure.rb', line 281

def write_header(file)
  # alter the BNF to exclude Elements and ENDSTR; then write to file
  # according to the modified BNF
  alt_bnf = BnfSpec.new(*Structure.bnf_spec.bnf_items[0..-3])
  self.write(file, alt_bnf)

  # if block is given, then yield to that block and then write the
  # footer afterwards
  if block_given?
    yield
    self.write_footer(file)
  end
end