Class: HTS::Bam

Inherits:
Hts
  • Object
show all
Includes:
Enumerable
Defined in:
lib/hts/bam.rb,
lib/hts/bam/aux.rb,
lib/hts/bam/flag.rb,
lib/hts/bam/cigar.rb,
lib/hts/bam/header.rb,
lib/hts/bam/record.rb

Defined Under Namespace

Classes: Aux, Cigar, Flag, Header, Record

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Hts

#closed?, #format, #format_version, #rewind, #seek, #struct, #tell, #to_ptr

Constructor Details

#initialize(file_name, mode = "r", index: nil, fai: nil, threads: nil, create_index: false) ⇒ Bam

Returns a new instance of Bam.

Raises:

  • (Errno::ENOENT)


29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/hts/bam.rb', line 29

def initialize(file_name, mode = "r", index: nil, fai: nil, threads: nil,
               create_index: false)
  if block_given?
    message = "HTS::Bam.new() dose not take block; Please use HTS::Bam.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       = mode
  @hts_file   = LibHTS.hts_open(@file_name, mode)

  raise Errno::ENOENT, "Failed to open #{@file_name}" if @hts_file.null?

  if fai
    r = LibHTS.hts_set_fai_filename(@hts_file, fai)
    raise "Failed to load fasta index: #{fai}" if r < 0
  end

  if threads&.> 0
    r = LibHTS.hts_set_threads(@hts_file, threads)
    raise "Failed to set number of threads: #{threads}" if r < 0
  end

  return if @mode[0] == "w"

  @header = Bam::Header.new(@hts_file)

  create_index(index) if create_index

  @idx = load_index(index)

  @start_position = tell
end

Instance Attribute Details

#file_nameObject (readonly)

Returns the value of attribute file_name.



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

def file_name
  @file_name
end

#headerObject (readonly)

Returns the value of attribute header.



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

def header
  @header
end

#index_nameObject (readonly)

Returns the value of attribute index_name.



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

def index_name
  @index_name
end

#modeObject (readonly)

Returns the value of attribute mode.



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

def mode
  @mode
end

Class Method Details

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



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

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

  begin
    yield file
  ensure
    file.close
  end
  file
end

Instance Method Details

#closeObject

Close the current file.



88
89
90
91
92
# File 'lib/hts/bam.rb', line 88

def close
  LibHTS.hts_idx_destroy(@idx) if @idx&.null?
  @idx = nil
  super
end

#create_index(index_name = nil) ⇒ Object



66
67
68
69
70
71
72
73
# File 'lib/hts/bam.rb', line 66

def create_index(index_name = nil)
  warn "Create index for #{@file_name} to #{index_name}"
  if index
    LibHTS.sam_index_build2(@file_name, index_name, -1)
  else
    LibHTS.sam_index_build(@file_name, -1)
  end
end

#eachObject

Iterate over each record. Record object is reused. Faster than each_copy.

Raises:

  • (IOError)


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

def each
  raise IOError, "closed stream" if closed?
  # Each does not always start at the beginning of the file.
  # This is the common behavior of IO objects in Ruby.
  # This may change in the future.
  return to_enum(__method__) unless block_given?

  bam1 = LibHTS.bam_init1
  record = Record.new(bam1, header)
  yield record while LibHTS.sam_read1(@hts_file, header, bam1) != -1
  self
end

#each_copyObject

Iterate over each record. Generate a new Record object each time. Slower than each.

Raises:

  • (IOError)


112
113
114
115
116
117
118
119
120
121
# File 'lib/hts/bam.rb', line 112

def each_copy
  raise IOError, "closed stream" if closed?
  return to_enum(__method__) unless block_given?

  while LibHTS.sam_read1(@hts_file, header, bam1 = LibHTS.bam_init1) != -1
    record = Record.new(bam1, header)
    yield record
  end
  self
end

#index_loaded?Boolean



83
84
85
# File 'lib/hts/bam.rb', line 83

def index_loaded?
  !@idx.null?
end

#load_index(index_name = nil) ⇒ Object



75
76
77
78
79
80
81
# File 'lib/hts/bam.rb', line 75

def load_index(index_name = nil)
  if index_name
    LibHTS.sam_index_load2(@hts_file, @file_name, index_name)
  else
    LibHTS.sam_index_load3(@hts_file, @file_name, nil, 2) # should be 3 ? (copy remote file to local?)
  end
end

#query(region) ⇒ Object

query [WIP]

Raises:

  • (IOError)


140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/hts/bam.rb', line 140

def query(region)
  raise IOError, "closed stream" if closed?
  raise "Index file is required to call the query method." unless index_loaded?

  qiter = LibHTS.sam_itr_querys(@idx, header, region)
  begin
    bam1 = LibHTS.bam_init1
    slen = LibHTS.sam_itr_next(@hts_file, qiter, bam1)
    while slen > 0
      yield Record.new(bam1, header)
      bam1 = LibHTS.bam_init1
      slen = LibHTS.sam_itr_next(@hts_file, qiter, bam1)
    end
  ensure
    LibHTS.hts_itr_destroy(qiter)
  end
end

#write(aln) ⇒ Object

Raises:

  • (IOError)


102
103
104
105
106
107
# File 'lib/hts/bam.rb', line 102

def write(aln)
  raise IOError, "closed stream" if closed?

  aln_dup = aln.dup
  LibHTS.sam_write1(@hts_file, header, aln_dup) > 0 || raise
end

#write_header(header) ⇒ Object

Raises:

  • (IOError)


94
95
96
97
98
99
100
# File 'lib/hts/bam.rb', line 94

def write_header(header)
  raise IOError, "closed stream" if closed?

  @header = header.dup
  LibHTS.hts_set_fai_filename(@hts_file, @file_name)
  LibHTS.sam_hdr_write(@hts_file, header)
end