Class: HTS::Tabix

Inherits:
Hts
  • Object
show all
Includes:
Enumerable
Defined in:
lib/hts/tabix.rb

Defined Under Namespace

Classes: MissingIndexError, OpenError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file_name, index: nil, threads: nil, build_index: false) ⇒ Tabix

Returns a new instance of Tabix.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/hts/tabix.rb', line 29

def initialize(file_name, index: nil, threads: nil, build_index: false)
  if block_given?
    message = "HTS::Tabix.new() does not take block; Please use HTS::Tabix.open() instead"
    raise message
  end

  # NOTE: Do not check for the existence of local files, since file_names may be remote URIs.

  @file_name  = file_name
  @index_name = index
  @mode       = "r"
  @nthreads   = threads
  @index_load_attempted = false
  @native = Native::TabixHandle.open(@file_name)

  set_threads(threads) if threads

  if build_index
    build_index(index)
    load_index(index)
  elsif index
    load_index(index)
  end
end

Instance Attribute Details

#file_nameObject (readonly)

Returns the value of attribute file_name.



15
16
17
# File 'lib/hts/tabix.rb', line 15

def file_name
  @file_name
end

#index_nameObject (readonly)

Returns the value of attribute index_name.



15
16
17
# File 'lib/hts/tabix.rb', line 15

def index_name
  @index_name
end

#modeObject (readonly)

Returns the value of attribute mode.



15
16
17
# File 'lib/hts/tabix.rb', line 15

def mode
  @mode
end

#nthreadsObject (readonly)

Returns the value of attribute nthreads.



15
16
17
# File 'lib/hts/tabix.rb', line 15

def nthreads
  @nthreads
end

Class Method Details

.open(*args, **kw) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/hts/tabix.rb', line 17

def self.open(*args, **kw)
  file = new(*args, **kw) # do not yield
  return file unless block_given?

  begin
    result = yield file
  ensure
    file.close
  end
  result
end

Instance Method Details

#build_index(index_name = nil, min_shift: 0) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/hts/tabix.rb', line 54

def build_index(index_name = nil, min_shift: 0)
  check_closed

  if index_name
    warn "Create index for #{@file_name} to #{index_name}"
    case Native::TabixHandle.build(@file_name, index_name, min_shift)
    when 0 # successful
    when -1 then raise "general failure"
    when -2 then raise "compression not BGZF"
    else raise "unknown error"
    end
  else
    warn "Create index for #{@file_name}"
    case Native::TabixHandle.build(@file_name, nil, min_shift)
    when 0 # successful
    when -1 then raise "general failure"
    when -2 then raise "compression not BGZF"
    else raise "unknown error"
    end
  end
  @index_name = index_name
  @index_load_attempted = false
  self # for method chaining
end

#closeObject



152
153
154
155
156
# File 'lib/hts/tabix.rb', line 152

def close
  return if closed?

  @native.close
end

#closed?Boolean

Returns:

  • (Boolean)


158
159
160
# File 'lib/hts/tabix.rb', line 158

def closed?
  @native.nil? || @native.closed?
end

#each_fields(region, start = nil, end_ = nil, &block) ⇒ Object

Explicit name for the legacy split-fields API.



116
117
118
# File 'lib/hts/tabix.rb', line 116

def each_fields(region, start = nil, end_ = nil, &block)
  query_with_mode(region, start, end_, :fields, nil, &block)
end

#each_line(region, start = nil, end_ = nil, &block) ⇒ Object

Iterate raw rows, allocating one String per row and no field Array.



121
122
123
# File 'lib/hts/tabix.rb', line 121

def each_line(region, start = nil, end_ = nil, &block)
  query_with_mode(region, start, end_, :line, nil, &block)
end

#each_selected_fields(region, *columns, &block) ⇒ Object

Extract only requested zero-based columns without materializing unused field strings. This Ruby implementation scans tab delimiters once.

Raises:

  • (ArgumentError)


127
128
129
130
131
132
133
134
135
136
137
# File 'lib/hts/tabix.rb', line 127

def each_selected_fields(region, *columns, &block)
  raise ArgumentError, "at least one column index is required" if columns.empty?

  normalized = columns.map do |column|
    index = Integer(column)
    raise ArgumentError, "column indices must be non-negative" if index.negative?

    index
  end
  query_with_mode(region, nil, nil, :selected, normalized, &block)
end

#file_formatObject



162
# File 'lib/hts/tabix.rb', line 162

def file_format = @native.file_format

#file_format_versionObject



163
# File 'lib/hts/tabix.rb', line 163

def file_format_version = @native.file_format_version

#index_loaded?Boolean

Returns:

  • (Boolean)


92
93
94
95
# File 'lib/hts/tabix.rb', line 92

def index_loaded?
  check_closed
  @native.index_loaded?
end

#load_index(index_name = nil) ⇒ Object

Raises:



79
80
81
82
83
# File 'lib/hts/tabix.rb', line 79

def load_index(index_name = nil)
  return self if try_load_index(index_name)

  raise MissingIndexError, "Failed to load index #{index_name || "for #{@file_name}"}"
end

#name2id(name) ⇒ Object



97
98
99
100
101
102
# File 'lib/hts/tabix.rb', line 97

def name2id(name)
  check_closed
  raise "Index file is required to call the name2id method." unless ensure_index_loaded

  @native.name2id(name)
end

#query(region, start = nil, end_ = nil, &block) ⇒ Object



111
112
113
# File 'lib/hts/tabix.rb', line 111

def query(region, start = nil, end_ = nil, &block)
  query_with_mode(region, start, end_, :fields, nil, &block)
end

#query_with_mode(region, start, end_, mode, columns, &block) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/hts/tabix.rb', line 139

def query_with_mode(region, start, end_, mode, columns, &block)
  check_closed
  raise "Index file is required to call the query method." unless ensure_index_loaded

  if start && end_
    queryi(name2id(region), start, end_, mode, columns, &block)
  elsif start.nil? && end_.nil?
    querys(region, mode, columns, &block)
  else
    raise ArgumentError, "start and end must be specified together"
  end
end

#seqnamesObject



104
105
106
107
108
109
# File 'lib/hts/tabix.rb', line 104

def seqnames
  check_closed
  raise "Index file is required to call the seqnames method." unless ensure_index_loaded

  @native.seqnames
end

#set_threads(n = nil) ⇒ Object

Raises:

  • (TypeError)


165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/hts/tabix.rb', line 165

def set_threads(n = nil)
  if n.nil?
    require "etc"
    n = [Etc.nprocessors - 1, 1].max
  end
  raise TypeError unless n.is_a?(Integer)
  raise ArgumentError, "Number of threads must be positive" if n < 1
  raise "Failed to set number of threads: #{n}" if @native.set_threads(n).negative?

  @nthreads = n
  self
end

#try_load_index(index_name = nil) ⇒ Object



85
86
87
88
89
90
# File 'lib/hts/tabix.rb', line 85

def try_load_index(index_name = nil)
  check_closed
  @index_name = index_name
  @index_load_attempted = true
  @native.load_index(index_name)
end