htslib 0.0.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd81ebe87741d1019acd341189ee0f8fb6ef09d3a10690686b3d40bdfea73076
4
- data.tar.gz: 39a7fa296cc1797c7cd6317923b3336c67f0cf16e8c9f7eb8ae8dbef9e6c7f56
3
+ metadata.gz: 87b06f64c496150db76d689f2cd06ba61e8ff424511be781bf17abbdf5d92d6c
4
+ data.tar.gz: 10126e01757aafb8fbb18c4f5d2f58541511226ddf922ffb253d29ccaf6c2027
5
5
  SHA512:
6
- metadata.gz: c349f647e798efc920492877807db88d03dfe88edf1434e733d38221ab15f1bea179ac524b3e26feb83c7063c878138918be3dcb30bcbbc583e0cc5bbbe1b8df
7
- data.tar.gz: 120052721db361d285968331d2091f4bfe17b45a4204443a591141bc12aef3b153866077dc85ddff63451873800f78db377a151ecbec7084b1f5f409fe5507b0
6
+ metadata.gz: 2bb5806ae23d58192a74c567767de193ed21f2b8f8f87cf2bef4ef9beccc62da684ce5a0b8a6a2b96afbdbd84fb13c14b27ea2738a4d70829b7d3c1a57396430
7
+ data.tar.gz: 9e49efbb3bdce645013e0aaa33dec335204a0c62f48cd0ab4b5128314b97f6237b5faec6a0acf0059d8a276e26323d93ad53c4b5e7e2c36b273592b970b7dfe4
data/README.md CHANGED
@@ -6,10 +6,7 @@
6
6
  [![DOI](https://zenodo.org/badge/247078205.svg)](https://zenodo.org/badge/latestdoi/247078205)
7
7
  [![Docs Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://rubydoc.info/gems/htslib)
8
8
 
9
- :dna: [HTSlib](https://github.com/samtools/htslib) - for Ruby
10
-
11
- Ruby-htslib is the Ruby bindings to HTSlib, a C library for processing high throughput sequencing (HTS) data.
12
- It will provide APIs to read and write file formats such as [SAM, BAM, VCF, and BCF](http://samtools.github.io/hts-specs/).
9
+ Ruby-htslib is the [Ruby](https://www.ruby-lang.org) bindings to [HTSlib](https://github.com/samtools/htslib), a C library for high-throughput sequencing data formats. It allows you to read and write file formats commonly used in genomics, such as [SAM, BAM, VCF, and BCF](http://samtools.github.io/hts-specs/) in the Ruby language.
13
10
 
14
11
  :apple: Feel free to fork it out if you can develop it!
15
12
 
@@ -17,7 +14,7 @@ It will provide APIs to read and write file formats such as [SAM, BAM, VCF, and
17
14
 
18
15
  ## Requirements
19
16
 
20
- * [Ruby](https://github.com/ruby/ruby) 2.7 or above.
17
+ * [Ruby](https://github.com/ruby/ruby) 3.1 or above.
21
18
  * [HTSlib](https://github.com/samtools/htslib)
22
19
  * Ubuntu : `apt install libhts-dev`
23
20
  * macOS : `brew install htslib`
@@ -30,7 +27,7 @@ gem install htslib
30
27
  ```
31
28
 
32
29
  If you have installed htslib with apt on Ubuntu or homebrew on Mac, [pkg-config](https://github.com/ruby-gnome/pkg-config)
33
- will automatically detect the location of the shared library.
30
+ will automatically detect the location of the shared library. If pkg-config does not work well, set `PKG_CONFIG_PATH`.
34
31
  Alternatively, you can specify the directory of the shared library by setting the environment variable `HTSLIBDIR`.
35
32
 
36
33
  ```sh
@@ -41,34 +38,35 @@ export HTSLIBDIR="/your/path/to/htslib" # libhts.so
41
38
 
42
39
  ### High level API
43
40
 
44
- A high-level API is under development.
45
- Classes such as `Cram` `Bam` `Bcf` `Faidx` `Tabix` are partially implemented.
46
-
47
- Read SAM / BAM - Sequence Alignment Map file
41
+ Read SAM / BAM / CRAM - Sequence Alignment Map file
48
42
 
49
43
  ```ruby
50
44
  require 'htslib'
51
45
 
52
- bam = HTS::Bam.new("a.bam")
46
+ bam = HTS::Bam.open("test/fixtures/moo.bam")
53
47
 
54
48
  bam.each do |r|
55
- p name: r.qname,
56
- flag: r.flag,
57
- pos: r.start + 1,
58
- mpos: r.mate_start + 1,
59
- mqual: r.mapping_quality,
60
- seq: r.sequence,
61
- cigar: r.cigar.to_s,
62
- qual: r.base_qualities.map { |i| (i + 33).chr }.join
49
+ pp name: r.qname,
50
+ flag: r.flag,
51
+ chrm: r.chrom,
52
+ strt: r.pos + 1,
53
+ mapq: r.mapq,
54
+ cigr: r.cigar.to_s,
55
+ mchr: r.mate_chrom,
56
+ mpos: r.mpos + 1,
57
+ isiz: r.isize,
58
+ seqs: r.seq,
59
+ qual: r.qual.map { |i| (i + 33).chr }.join,
60
+ MC: r.aux("MC")
63
61
  end
64
62
 
65
63
  bam.close
66
64
  ```
67
65
 
68
- Read VCF / BCF - Variant Call Format
66
+ Read VCF / BCF - Variant Call Format file
69
67
 
70
68
  ```ruby
71
- bcf = HTS::Bcf.new("b.bcf")
69
+ bcf = HTS::Bcf.open("b.bcf")
72
70
 
73
71
  bcf.each do |r|
74
72
  p chrom: r.chrom,
@@ -77,17 +75,17 @@ bcf.each do |r|
77
75
  qual: r.qual.round(2),
78
76
  ref: r.ref,
79
77
  alt: r.alt,
80
- filter: r.filter
78
+ filter: r.filter,
79
+ info: r.info.to_h,
80
+ format: r.format.to_h
81
81
  end
82
82
 
83
83
  bcf.close
84
84
  ```
85
85
 
86
- The methods for reading are implemented first. Methods for writing will be implemented in the coming days.
87
-
88
86
  ### Low level API
89
87
 
90
- `HTS::LibHTS` provides native functions.
88
+ `HTS::LibHTS` provides native C functions.
91
89
 
92
90
  ```ruby
93
91
  require 'htslib'
@@ -98,19 +96,20 @@ p b[:category]
98
96
  p b[:format]
99
97
  ```
100
98
 
101
- Note: Only some C structs are implemented with FFI's ManagedStruct, which frees memory when Ruby's garbage collection fires. Other structs will need to be freed manually.
99
+ Note: htslib makes extensive use of macro functions for speed. you cannot use C macro functions in Ruby if they are not reimplemented in ruby-htslib. Only small number of C structs are implemented with FFI's ManagedStruct, which frees memory when Ruby's garbage collection fires. Other structs will need to be freed manually.
102
100
 
103
101
  ### Need more speed?
104
102
 
105
- Try [htslib.cr](https://github.com/bio-crystal/htslib.cr). htslib.cr is implemented in Crystal language and provides an API compatible with ruby-htslib. crsytal language is not as flexible as Ruby language. If you have a clear idea of the manipulation you want to do and need to perform it many times, then by all means try to implement a command line tool using htslib.cr. The Crystal language is very fast and can perform almost as well as the Rust and C languages.
103
+ Try Crystal. [htslib.cr](https://github.com/bio-crystal/htslib.cr) is implemented in Crystal language and provides an API compatible with ruby-htslib. Crsytal language is not as flexible as Ruby language. You can not use `eval` methods, and you must always be careful with the data types. Writing one-time scripts in Crystal or playing with REPL may not be as much fun. However, if you have a clear idea of what you want to do in your mind, have already written code in Ruby, and need to run them over and over, try creating a command line tool in Crystal. The Crystal language is fast, as fast as the Rust and C languages. It will give you great power to create tools.
106
104
 
107
105
  ## Documentation
108
106
 
107
+ * [API Documentation (develop branch)](https://kojix2.github.io/ruby-htslib/)
109
108
  * [RubyDoc.info - HTSlib](https://rdoc.info/gems/htslib)
110
109
 
111
110
  ## Development
112
111
 
113
- To get started with development
112
+ To get started with development:
114
113
 
115
114
  ```sh
116
115
  git clone --recursive https://github.com/kojix2/ruby-htslib
@@ -120,10 +119,16 @@ bundle exec rake htslib:build
120
119
  bundle exec rake test
121
120
  ```
122
121
 
122
+ [GNU Autotools](https://en.wikipedia.org/wiki/GNU_Autotools) is required to compile htslib.
123
+
123
124
  Many macro functions are used in HTSlib. Since these macro functions cannot be called using FFI, they must be reimplemented in Ruby.
124
125
 
125
- * Actively use the advanced features of Ruby.
126
- * Consider compatibility with [htslib.cr](https://github.com/bio-crystal/htslib.cr) to some extent.
126
+ * Use the new version of Ruby to take full advantage of Ruby's potential.
127
+ * This is possible because we have a small number of users. What a deal!
128
+ * Remain compatibile with [htslib.cr](https://github.com/bio-crystal/htslib.cr).
129
+ * The most difficult part is the return value. In the Crystal language, methods are expected to return only one type. On the other hand, in the Ruby language, methods that return multiple classes are very common. For example, in the Crystal language, the compiler gets confused if the return value is one of six types: Int32, Int64, Float32, Float64, Nil, or String. In fact Crystal can do this. But the code gets a little messy. In Ruby, this is very common and doesn't cause any problems.
130
+
131
+ In the script directory, there are several tools to help implement ruby-htslib. These tools may be forked into independent repository in the future.
127
132
 
128
133
  #### FFI Extensions
129
134
 
@@ -131,7 +136,6 @@ Many macro functions are used in HTSlib. Since these macro functions cannot be c
131
136
 
132
137
  #### Automatic generation or automatic validation (Future plan)
133
138
 
134
-
135
139
  + [c2ffi](https://github.com/rpav/c2ffi) is a tool to create JSON format metadata from C header files. It is planned to use c2ffi to automatically generate bindings or tests.
136
140
 
137
141
  ## Contributing
@@ -144,15 +148,18 @@ Ruby-htslib is a library under development, so even small improvements like typo
144
148
  * Suggest or add new features
145
149
  * [financial contributions](https://github.com/sponsors/kojix2)
146
150
 
151
+
147
152
  ```
148
- Do you need commit rights to my repository?
153
+ # Ownership and Commitment Rights
154
+
155
+ Do you need commit rights to ruby-htslib repository?
149
156
  Do you want to get admin rights and take over the project?
150
157
  If so, please feel free to contact us @kojix2.
151
158
  ```
152
159
 
153
160
  #### Why do you implement htslib in a language like Ruby, which is not widely used in the bioinformatics?
154
161
 
155
- One of the greatest joys of using a minor language like Ruby in bioinformatics is that there is nothing stopping you from reinventing the wheel. Reinventing the wheel can be fun. But with languages like Python and R, where many bioinformatics masters work, there is no chance left for beginners to create htslib bindings. Bioinformatics file formats, libraries and tools are very complex and I don't know how to understand them. So I wanted to implement the HTSLib binding to better understand how to use the file formats and tools. And that effort is still going on today...
162
+ One of the greatest joys of using a minor language like Ruby in bioinformatics is that there is nothing stopping you from reinventing the wheel. Reinventing the wheel can be fun. But with languages like Python and R, where many bioinformatics masters work, there is no chance left for beginners to create htslib bindings. Bioinformatics file formats, libraries and tools are very complex and I don't know how to understand them. So I wanted to implement the HTSLib binding myself to better understand how the pioneers of bioinformatics felt when establishing the file format and how they created their tools. I hope one day we can work on bioinformatics using Ruby and Crystal languages, not to replace other languages such as Python and R, but to add new power and value to this advancing field.
156
163
 
157
164
  ## Links
158
165
 
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTS
4
+ class Bam < Hts
5
+ # Auxiliary record data
6
+ class Aux
7
+ def initialize(record)
8
+ @record = record
9
+ end
10
+
11
+ def get(key, type = nil)
12
+ aux = LibHTS.bam_aux_get(@record.struct, key)
13
+ return nil if aux.null?
14
+
15
+ type ||= aux.read_string(1)
16
+
17
+ # A (character), B (general array),
18
+ # f (real number), H (hexadecimal array),
19
+ # i (integer), or Z (string).
20
+
21
+ case type
22
+ when "i", "I", "c", "C", "s", "S"
23
+ LibHTS.bam_aux2i(aux)
24
+ when "f", "d"
25
+ LibHTS.bam_aux2f(aux)
26
+ when "Z", "H"
27
+ LibHTS.bam_aux2Z(aux)
28
+ when "A" # char
29
+ LibHTS.bam_aux2A(aux).chr
30
+ else
31
+ raise NotImplementedError, "type: #{t}"
32
+ end
33
+ end
34
+
35
+ def [](key)
36
+ get(key)
37
+ end
38
+ end
39
+ end
40
+ end
data/lib/hts/bam/cigar.rb CHANGED
@@ -1,33 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Based on hts-python
4
- # https://github.com/quinlan-lab/hts-python
5
-
6
3
  module HTS
7
- class Bam
4
+ class Bam < Hts
5
+ # CIGAR string
8
6
  class Cigar
9
7
  include Enumerable
10
8
 
11
9
  def initialize(pointer, n_cigar)
12
- @pointer = pointer
13
10
  @n_cigar = n_cigar
14
- end
15
-
16
- def to_ptr
17
- @pointer
11
+ # Read the pointer before the memory is changed.
12
+ # Especially when called from a block of `each` iterator.
13
+ @c = pointer.read_array_of_uint32(n_cigar)
18
14
  end
19
15
 
20
16
  def to_s
21
- to_a.flatten.join
17
+ map { |op, len| "#{len}#{op}" }.join
22
18
  end
23
19
 
24
20
  def each
25
21
  return to_enum(__method__) unless block_given?
26
22
 
27
- @n_cigar.times do |i|
28
- c = @pointer[i].read_uint32
29
- yield [LibHTS.bam_cigar_oplen(c),
30
- LibHTS.bam_cigar_opchr(c)]
23
+ @c.each do |c|
24
+ op = LibHTS.bam_cigar_opchr(c)
25
+ len = LibHTS.bam_cigar_oplen(c)
26
+ yield [op, len]
31
27
  end
32
28
  end
33
29
  end
data/lib/hts/bam/flag.rb CHANGED
@@ -4,7 +4,8 @@
4
4
  # https://github.com/brentp/hts-nim/blob/master/src/hts/bam/flag.nim
5
5
 
6
6
  module HTS
7
- class Bam
7
+ class Bam < Hts
8
+ # SAM flags
8
9
  class Flag
9
10
  def initialize(flag_value)
10
11
  raise TypeError unless flag_value.is_a? Integer
@@ -27,70 +28,38 @@ module HTS
27
28
  # BAM_FDUP = 1024
28
29
  # BAM_FSUPPLEMENTARY = 2048
29
30
 
30
- # TODO: Enabling bitwise operations
31
- # hts-nim
32
- # proc `and`*(f: Flag, o: uint16): uint16 {. borrow, inline .}
33
- # proc `and`*(f: Flag, o: Flag): uint16 {. borrow, inline .}
34
- # proc `or`*(f: Flag, o: uint16): uint16 {. borrow .}
35
- # proc `or`*(o: uint16, f: Flag): uint16 {. borrow .}
36
- # proc `==`*(f: Flag, o: Flag): bool {. borrow, inline .}
37
- # proc `==`*(f: Flag, o: uint16): bool {. borrow, inline .}
38
- # proc `==`*(o: uint16, f: Flag): bool {. borrow, inline .}
39
-
40
- def paired?
41
- has_flag? LibHTS::BAM_FPAIRED
42
- end
43
-
44
- def proper_pair?
45
- has_flag? LibHTS::BAM_FPROPER_PAIR
46
- end
47
-
48
- def unmapped?
49
- has_flag? LibHTS::BAM_FUNMAP
50
- end
51
-
52
- def mate_unmapped?
53
- has_flag? LibHTS::BAM_FMUNMAP
54
- end
55
-
56
- def reverse?
57
- has_flag? LibHTS::BAM_FREVERSE
58
- end
59
-
60
- def mate_reverse?
61
- has_flag? LibHTS::BAM_FMREVERSE
62
- end
63
-
64
- def read1?
65
- has_flag? LibHTS::BAM_FREAD1
66
- end
67
-
68
- def read2?
69
- has_flag? LibHTS::BAM_FREAD2
70
- end
71
-
72
- def secondary?
73
- has_flag? LibHTS::BAM_FSECONDARY
74
- end
75
-
76
- def qcfail?
77
- has_flag? LibHTS::BAM_FQCFAIL
78
- end
79
-
80
- def dup?
81
- has_flag? LibHTS::BAM_FDUP
31
+ # TODO: Enabling bitwise operations?
32
+
33
+ TABLE = { paired?: LibHTS::BAM_FPAIRED,
34
+ proper_pair?: LibHTS::BAM_FPROPER_PAIR,
35
+ unmapped?: LibHTS::BAM_FUNMAP,
36
+ mate_unmapped?: LibHTS::BAM_FMUNMAP,
37
+ reverse?: LibHTS::BAM_FREVERSE,
38
+ mate_reverse?: LibHTS::BAM_FMREVERSE,
39
+ read1?: LibHTS::BAM_FREAD1,
40
+ read2?: LibHTS::BAM_FREAD2,
41
+ secondary?: LibHTS::BAM_FSECONDARY,
42
+ qcfail?: LibHTS::BAM_FQCFAIL,
43
+ duplicate?: LibHTS::BAM_FDUP,
44
+ supplementary?: LibHTS::BAM_FSUPPLEMENTARY }.freeze
45
+
46
+ TABLE.each do |name, v|
47
+ define_method(name) do
48
+ has_flag?(v)
49
+ end
82
50
  end
83
51
 
84
- def supplementary?
85
- has_flag? LibHTS::BAM_FSUPPLEMENTARY
52
+ def has_flag?(f)
53
+ (@value & f) != 0
86
54
  end
87
55
 
88
- def has_flag?(m)
89
- (@value & m) != 0
56
+ def to_i
57
+ @value
90
58
  end
91
59
 
92
60
  def to_s
93
- "0x#{format('%x', @value)}\t#{@value}\t#{LibHTS.bam_flag2str(@value)}"
61
+ LibHTS.bam_flag2str(@value)
62
+ # "0x#{format('%x', @value)}\t#{@value}\t#{LibHTS.bam_flag2str(@value)}"
94
63
  end
95
64
  end
96
65
  end
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Based on hts-python
4
- # https://github.com/quinlan-lab/hts-python
5
-
6
3
  module HTS
7
- class Bam
4
+ class Bam < Hts
5
+ # A class for working with alignment header.
8
6
  class Header
9
7
  def initialize(hts_file)
10
8
  @sam_hdr = LibHTS.sam_hdr_read(hts_file)
@@ -28,7 +26,7 @@ module HTS
28
26
  end
29
27
  end
30
28
 
31
- def target_lengths
29
+ def target_len
32
30
  Array.new(target_count) do |i|
33
31
  LibHTS.sam_hdr_tid2len(@sam_hdr, i)
34
32
  end
@@ -1,13 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Based on hts-python
4
- # https://github.com/quinlan-lab/hts-python
3
+ require_relative "flag"
4
+ require_relative "cigar"
5
+ require_relative "aux"
5
6
 
6
7
  module HTS
7
- class Bam
8
+ class Bam < Hts
9
+ # A class for working with alignment records.
8
10
  class Record
9
11
  SEQ_NT16_STR = "=ACMGRSVTWYHKDBN"
10
12
 
13
+ attr_reader :header
14
+
11
15
  def initialize(bam1_t, header)
12
16
  @bam1 = bam1_t
13
17
  @header = header
@@ -21,16 +25,6 @@ module HTS
21
25
  @bam1.to_ptr
22
26
  end
23
27
 
24
- attr_reader :header
25
-
26
- # def initialize_copy
27
- # super
28
- # end
29
-
30
- def self.rom_sam_str; end
31
-
32
- def tags; end
33
-
34
28
  # returns the query name.
35
29
  def qname
36
30
  LibHTS.bam_get_qname(@bam1).read_string
@@ -46,26 +40,52 @@ module HTS
46
40
  @bam1[:core][:tid]
47
41
  end
48
42
 
43
+ def tid=(tid)
44
+ @bam1[:core][:tid] = tid
45
+ end
46
+
49
47
  # returns the tid of the mate or -1 if not mapped.
50
- def mate_tid
48
+ def mtid
51
49
  @bam1[:core][:mtid]
52
50
  end
53
51
 
52
+ def mtid=(mtid)
53
+ @bam1[:core][:mtid] = mtid
54
+ end
55
+
54
56
  # returns 0-based start position.
55
- def start
57
+ def pos
56
58
  @bam1[:core][:pos]
57
59
  end
58
60
 
59
- # returns end position of the read.
60
- def stop
61
- LibHTS.bam_endpos @bam1
61
+ def pos=(pos)
62
+ @bam1[:core][:pos] = pos
62
63
  end
63
64
 
64
65
  # returns 0-based mate position
65
- def mate_start
66
+ def mate_pos
66
67
  @bam1[:core][:mpos]
67
68
  end
68
- alias mate_pos mate_start
69
+
70
+ def mate_pos=(mpos)
71
+ @bam1[:core][:mpos] = mpos
72
+ end
73
+
74
+ alias mpos mate_pos
75
+ alias mpos= mate_pos=
76
+
77
+ def bin
78
+ @bam1[:core][:bin]
79
+ end
80
+
81
+ def bin=(bin)
82
+ @bam1[:core][:bin] = bin
83
+ end
84
+
85
+ # returns end position of the read.
86
+ def endpos
87
+ LibHTS.bam_endpos @bam1
88
+ end
69
89
 
70
90
  # returns the chromosome or '' if not mapped.
71
91
  def chrom
@@ -74,37 +94,43 @@ module HTS
74
94
  LibHTS.sam_hdr_tid2name(@header, tid)
75
95
  end
76
96
 
77
- # returns the chromosome or '' if not mapped.
78
- def contig
79
- chrom
80
- end
97
+ alias contig chrom
81
98
 
82
99
  # returns the chromosome of the mate or '' if not mapped.
83
100
  def mate_chrom
84
- mtid = mate_tid
85
101
  return "" if mtid == -1
86
102
 
87
103
  LibHTS.sam_hdr_tid2name(@header, mtid)
88
104
  end
89
105
 
106
+ alias mate_contig mate_chrom
107
+
108
+ # Get strand information.
90
109
  def strand
91
110
  LibHTS.bam_is_rev(@bam1) ? "-" : "+"
92
111
  end
93
112
 
94
- # def start=(v)
95
- # raise 'Not Implemented'
96
- # end
97
-
98
113
  # insert size
99
114
  def insert_size
100
115
  @bam1[:core][:isize]
101
116
  end
102
117
 
118
+ def insert_size=(isize)
119
+ @bam1[:core][:isize] = isize
120
+ end
121
+
122
+ alias isize insert_size
123
+ alias isize= insert_size=
124
+
103
125
  # mapping quality
104
- def mapping_quality
126
+ def mapq
105
127
  @bam1[:core][:qual]
106
128
  end
107
129
 
130
+ def mapq=(mapq)
131
+ @bam1[:core][:qual] = mapq
132
+ end
133
+
108
134
  # returns a `Cigar` object.
109
135
  def cigar
110
136
  Cigar.new(LibHTS.bam_get_cigar(@bam1), @bam1[:core][:n_cigar])
@@ -125,7 +151,7 @@ module HTS
125
151
  end
126
152
 
127
153
  # return the read sequence
128
- def sequence
154
+ def seq
129
155
  r = LibHTS.bam_get_seq(@bam1)
130
156
  seq = String.new
131
157
  (@bam1[:core][:l_qseq]).times do |i|
@@ -133,59 +159,74 @@ module HTS
133
159
  end
134
160
  seq
135
161
  end
162
+ alias sequence seq
163
+
164
+ def len
165
+ @bam1[:core][:l_qseq]
166
+ end
136
167
 
137
168
  # return only the base of the requested index "i" of the query sequence.
138
- def base_at(n)
169
+ def base(n)
139
170
  n += @bam1[:core][:l_qseq] if n < 0
140
- return "." if (n >= @bam1[:core][:l_qseq]) || (n < 0) # eg. base_at(-1000)
171
+ return "." if (n >= @bam1[:core][:l_qseq]) || (n < 0) # eg. base(-1000)
141
172
 
142
173
  r = LibHTS.bam_get_seq(@bam1)
143
174
  SEQ_NT16_STR[LibHTS.bam_seqi(r, n)]
144
175
  end
145
176
 
146
177
  # return the base qualities
147
- def base_qualities
178
+ def qual
148
179
  q_ptr = LibHTS.bam_get_qual(@bam1)
149
180
  q_ptr.read_array_of_uint8(@bam1[:core][:l_qseq])
150
181
  end
151
182
 
152
183
  # return only the base quality of the requested index "i" of the query sequence.
153
- def base_quality_at(n)
184
+ def base_qual(n)
154
185
  n += @bam1[:core][:l_qseq] if n < 0
155
- return 0 if (n >= @bam1[:core][:l_qseq]) || (n < 0) # eg. base_quality_at(-1000)
186
+ return 0 if (n >= @bam1[:core][:l_qseq]) || (n < 0) # eg. base_qual(-1000)
156
187
 
157
188
  q_ptr = LibHTS.bam_get_qual(@bam1)
158
189
  q_ptr.get_uint8(n)
159
190
  end
160
191
 
161
- def flag_str
162
- LibHTS.bam_flag2str(@bam1[:core][:flag])
163
- end
164
-
165
192
  # returns a `Flag` object.
166
193
  def flag
167
194
  Flag.new(@bam1[:core][:flag])
168
195
  end
169
196
 
170
- def tag(str)
171
- aux = LibHTS.bam_aux_get(@bam1, str)
172
- return nil if aux.null?
197
+ def flag=(flag)
198
+ case flag
199
+ when Integer
200
+ @bam1[:core][:flag] = flag
201
+ when Flag
202
+ @bam1[:core][:flag] = flag.value
203
+ else
204
+ raise "Invalid flag type: #{flag.class}"
205
+ end
206
+ end
207
+
208
+ # retruns the auxillary fields.
209
+ def aux(key = nil)
210
+ aux = Aux.new(self)
211
+ if key
212
+ aux.get(key)
213
+ else
214
+ aux
215
+ end
216
+ end
217
+
218
+ # TODO: add a method to get the auxillary fields as a hash.
219
+
220
+ # TODO: add a method to set the auxillary fields.
173
221
 
174
- t = aux.read_string(1)
222
+ # TODO: add a method to remove the auxillary fields.
175
223
 
176
- # A (character), B (general array),
177
- # f (real number), H (hexadecimal array),
178
- # i (integer), or Z (string).
224
+ # TODO: add a method to set variable length data (qname, cigar, seq, qual).
179
225
 
180
- case t
181
- when "i", "I", "c", "C", "s", "S"
182
- LibHTS.bam_aux2i(aux)
183
- when "f", "d"
184
- LibHTS.bam_aux2f(aux)
185
- when "Z", "H"
186
- LibHTS.bam_aux2Z(aux)
187
- when "A" # char
188
- LibHTS.bam_aux2A(aux).chr
226
+ # Calling flag is delegated to the Flag object.
227
+ Flag::TABLE.each_key do |m|
228
+ define_method(m) do
229
+ flag.send(m)
189
230
  end
190
231
  end
191
232