class Mspire::Mzml::IndexList

A simple array of indices but [] has been overloaded to find an index by name

index_list[0]  # the first index
index_list.map(&:name) # -> [:spectrum, :chromatogram]
index_list[:spectrum]  # the spectrum index
index_list[:chromatogram]  # the chromatogram index

Public Class Methods

create_index_list(io) click to toggle source

Reads through and captures start bytes @return [Mspire::Mzml::IndexList]

# File lib/mspire/mzml/index_list.rb, line 82
def create_index_list(io)
  indices_hash = io.bookmark(true) do |inner_io|   # sets to beginning of file
    indices = {:spectrum => {}, :chromatogram => {}}
    byte_total = 0
    io.each do |line|
      if md=%r{<(spectrum|chromatogram).*?id=['"](.*?)['"][ >]}.match(line)
        indices[md[1].to_sym][md[2]] = byte_total + md.pre_match.bytesize
      end
      byte_total += line.bytesize
    end
    indices
  end

  indices = indices_hash.map do |sym, hash|
    indices = Index.new ; ids = []
    hash.each {|id, startbyte| ids << id ; indices << startbyte }
    indices.ids = ids ; indices.name = sym
    indices
  end
  # we only return an index if there were some guys there
  indices.delete_if {|ind| ind.size == 0 }
  IndexList.new(indices)
end
from_io(io) click to toggle source

either reads in from file or creates an IndexList

# File lib/mspire/mzml/index_list.rb, line 39
def from_io(io)
  read_index_list(io) || create_index_list(io)
end
index_offset(io, tag='indexListOffset', bytes_backwards=200) click to toggle source

returns an Integer or nil if not found does a single jump backwards from the tail of the file looking for an xml element based on tag. If it is not found, returns nil

# File lib/mspire/mzml/index_list.rb, line 46
def index_offset(io, tag='indexListOffset', bytes_backwards=200)
  tag_re = %r{<#{tag}>([\-\d]+)</#{tag}>}
    io.pos = (io.size - 1) - bytes_backwards
  md = io.readlines("\n").map {|line| line.match(tag_re) }.compact.shift
  md[1].to_i if md
end
read_index_list(io) click to toggle source

@return [Mspire::Mzml::IndexList] or nil if there is no indexList in the mzML

# File lib/mspire/mzml/index_list.rb, line 55
def read_index_list(io)
  if (offset = index_offset(io))
    io.seek(offset)
    # TODO: pass in encoding (as second nil)
    xml = Nokogiri::XML.parse(io.read, nil, nil, Parser::NOBLANKS)
    index_list = xml.root
    num_indices = index_list['count'].to_i
    array = index_list.children.map do |index_n|
      #index = Index.new(index_n['name'])
      index = Index.new
      index.name = index_n['name'].to_sym
      ids = []
      index_n.children.each do |offset_n| 
        if offset_n.name == 'offset'  # <- pwiz sometimes makes an index with no offsets, in violation of the mzML 1.1 schema--this simple check circumvents their mistake
          index << offset_n.text.to_i 
          ids << offset_n['idRef']
        end
      end
      index.ids = ids
      index
    end
    IndexList.new(array)
  end
end

Public Instance Methods

[](int_or_symbol) click to toggle source

@param [Object] an Integer (index number) or a Symbol (:spectrum or

:chromatogram)

@return [Mspire::Mzml::Index] an index object

# File lib/mspire/mzml/index_list.rb, line 18
def [](int_or_symbol)
  if int_or_symbol.is_a?(Integer)
    old_bracket_slice(int_or_symbol)
  else
    self.find {|index| index.name == int_or_symbol }
  end
end
each_pair(&block) click to toggle source

returns each name and associated index object

# File lib/mspire/mzml/index_list.rb, line 31
def each_pair(&block)
  block or return enum_for __method__
  each {|index| block.call([index.name, index]) }
end
keys() click to toggle source
# File lib/mspire/mzml/index_list.rb, line 26
def keys
  self.map(&:name)
end