ABIF 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/ABIF.gemspec +26 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +34 -0
- data/Rakefile +12 -0
- data/bin/abifcli +3 -0
- data/lib/ABIF.rb +11 -0
- data/lib/ABIF/cli.rb +91 -0
- data/lib/ABIF/file.rb +236 -0
- data/lib/ABIF/version.rb +3 -0
- data/test/files/invalid.abif +44 -0
- data/test/files/valid.abif +0 -0
- data/test/lib/ABIF/file_test.rb +189 -0
- data/test/test_helper.rb +4 -0
- metadata +121 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8209086fa0fd89bb8c512306fbb483b238265a20
|
4
|
+
data.tar.gz: e439aefb5b8f8d864365fdbd94a29ed8c6d5d422
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ca2ff2b3f0a162039a130d691093508540d1d3eb66050a5e99e35f419b1d270c2ceca5f894fa6d7e04246d42adec0aef8f84b92d635a4040e8a0ca1be849ac94
|
7
|
+
data.tar.gz: f3041d14381c0aae42617f1e2cc2a724b427392cdd65cfc33640e281f47e2515bf27e9a1e91bd99be3207c893f88d2e9f119d1e74f026e1ac9e28400e91eb963
|
data/.gitignore
ADDED
data/ABIF.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ABIF/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ABIF"
|
8
|
+
spec.version = ABIF::VERSION
|
9
|
+
spec.authors = ["Sascha Willuweit"]
|
10
|
+
spec.email = ["s@rprojekt.org"]
|
11
|
+
spec.description = %q{ABIF file format reader/parse/plotter.}
|
12
|
+
spec.summary = %q{Handle/Parse/Plot ABIF (Applied Biosystems Genetic Analysis Data File Format) FSA, AB1 and HID files.}
|
13
|
+
spec.homepage = "https://github.com/545ch4/ABIF"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "thor"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "minitest"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
end
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Sascha Willuweit
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# ABIF
|
2
|
+
|
3
|
+
Handle ABIF (Applied Biosystems Genetic Analysis Data File Format) FSA, AB1 and HID files.
|
4
|
+
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'ABIF'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install ABIF
|
19
|
+
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
file = ABIF::File.new(<.fsa|ab1|hid file or IO stream>)
|
24
|
+
puts file.data.keys
|
25
|
+
puts file.data['RunN_1']
|
26
|
+
|
27
|
+
|
28
|
+
## Contributing
|
29
|
+
|
30
|
+
1. Fork it
|
31
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
32
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
33
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
34
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/abifcli
ADDED
data/lib/ABIF.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "ABIF/version"
|
2
|
+
require "ABIF/file"
|
3
|
+
# This program is a ABIF file (Applied Biosystems Genetic Analysis Data File Format)
|
4
|
+
# reader. It takes a ABIF file (.fsa) or HID file (.hid) and reading its content to several arrays of (named) datapoints.
|
5
|
+
# For in-depths description of the file format see http://www.appliedbiosystems.com/support/software_community/ABIF_File_Format.pdf
|
6
|
+
#
|
7
|
+
# Author:: Sascha Willuweit (s@rprojekt.org)
|
8
|
+
# Copyright:: Copyright (c) 2013 Sascha Willuweit
|
9
|
+
# License:: CreativeCommons Attribution-NonCommercial-ShareAlike 3.0 Unported License (see http://creativecommons.org/licenses/by-nc-sa/3.0/)
|
10
|
+
module ABIF
|
11
|
+
end
|
data/lib/ABIF/cli.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'open3'
|
4
|
+
require 'abif'
|
5
|
+
|
6
|
+
module ABIF
|
7
|
+
class CLI < Thor
|
8
|
+
class_option :verbose, :type => :boolean
|
9
|
+
class_option :version, :type => :boolean
|
10
|
+
|
11
|
+
desc "test FILE", "Test validity of FILE"
|
12
|
+
def test(filename)
|
13
|
+
print_version if options[:version]
|
14
|
+
puts ABIF::File.supported? filename, options.select{|option| [].include? option}
|
15
|
+
end
|
16
|
+
|
17
|
+
option :format, :type => :string, :default => 'dat'
|
18
|
+
option :normalize, :type => :string, :default => 'none'
|
19
|
+
desc "parse FILE", "parse FILE "
|
20
|
+
def parse(filename)
|
21
|
+
print_version if options[:version]
|
22
|
+
|
23
|
+
f = ABIF::File.new filename, options.select{|option| [:normalize].include? option}
|
24
|
+
refrence_datapoints = f.data['DATA_1'].size
|
25
|
+
channels = f.data.keys.select{|channel| channel.include?('DATA_') && f.data[channel].size == refrence_datapoints}
|
26
|
+
case options[:format]
|
27
|
+
when 'csv'
|
28
|
+
puts "index," << channels.join(",")
|
29
|
+
refrence_datapoints.times do |i|
|
30
|
+
puts "#{i}," << channels.map{|channel| f.data[channel][i]}.join(",")
|
31
|
+
end
|
32
|
+
when 'raw'
|
33
|
+
f.data.each do |key, d|
|
34
|
+
puts "#{key} (#{f.data_params[key].join(',')}): #{d.inspect}"
|
35
|
+
end
|
36
|
+
else
|
37
|
+
puts "index\t" << channels.join("\t")
|
38
|
+
refrence_datapoints.times do |i|
|
39
|
+
puts "#{i}\t" << channels.map{|channel| f.data[channel][i]}.join("\t")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
exit 0
|
43
|
+
end
|
44
|
+
|
45
|
+
option :format, :type => :string, :default => 'png'
|
46
|
+
option :size, :type => :string, :default => '5000,6000'
|
47
|
+
option :normalize, :type => :string, :default => 'none'
|
48
|
+
desc "plot FILE OUTFILE", "plot FILE into OUTFILE"
|
49
|
+
def plot(filename, outfilename)
|
50
|
+
print_version if options[:version]
|
51
|
+
|
52
|
+
#colors = ['blue', 'green', 'black', 'red', 'orange', 'purple']
|
53
|
+
|
54
|
+
f = ABIF::File.new filename, options.select{|option| [:normalize].include? option}
|
55
|
+
tmpfile = Tempfile.new('abifcli.dat')
|
56
|
+
|
57
|
+
refrence_datapoints = f.data['DATA_1'].size
|
58
|
+
channels = f.data.keys.select{|channel| channel.include?('DATA_') && f.data[channel].size == refrence_datapoints}
|
59
|
+
tmpfile.puts "index\t" << channels.join("\t")
|
60
|
+
refrence_datapoints.times do |i|
|
61
|
+
tmpfile.puts "#{i}\t" << channels.map{|channel| f.data[channel][i]}.join("\t")
|
62
|
+
end
|
63
|
+
tmpfile.close
|
64
|
+
|
65
|
+
IO.popen(%w{gnuplot}, 'r+') do |gnuplot|
|
66
|
+
gnuplot.puts "set terminal #{options[:format].inspect} size #{options[:size]}"
|
67
|
+
gnuplot.puts "set output #{outfilename.inspect}"
|
68
|
+
gnuplot.puts "set multiplot layout #{channels.size}, 1 title #{filename.inspect}"
|
69
|
+
channels.each_with_index.map do |channel, i|
|
70
|
+
gnuplot.puts "set title #{channel.inspect}"
|
71
|
+
gnuplot.puts "unset key"
|
72
|
+
gnuplot.puts "plot #{tmpfile.path.inspect} using 1:#{i + 2} with lines lt 1 lc rgb 'grey' lw 1"
|
73
|
+
end
|
74
|
+
gnuplot.puts "unset multiplot"
|
75
|
+
gnuplot.puts "exit"
|
76
|
+
gnuplot.close_write
|
77
|
+
end
|
78
|
+
|
79
|
+
tmpfile.unlink
|
80
|
+
|
81
|
+
exit 0
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def print_version
|
87
|
+
puts "abifcli version #{ABIF::VERSION}"
|
88
|
+
exit 0
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/ABIF/file.rb
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
module ABIF
|
5
|
+
# This class holds the FSA/HID file format data. It's initialized given the filename or an IO object.
|
6
|
+
# Options are:
|
7
|
+
# [:normalize] All channels are normalized with respect to their 500-datapoint-tail assuming it means-up to 0.
|
8
|
+
class File
|
9
|
+
attr_reader :filetype, :fileversion, :data, :data_params
|
10
|
+
|
11
|
+
def self.supported?(filename_or_io, options = {})
|
12
|
+
ft = nil
|
13
|
+
fv = 0
|
14
|
+
begin
|
15
|
+
io = filename_or_io.respond_to?(:seek) ? filename_or_io : ::File.open(filename_or_io, 'rb')
|
16
|
+
(ft, fv) = io.read(6).unpack('A4S>')
|
17
|
+
rescue Exception => e
|
18
|
+
raise IOError.new "Error reding ABIF file: #{e}"
|
19
|
+
ensure
|
20
|
+
io.close unless io.nil? || !io.respond_to?(:close)
|
21
|
+
end
|
22
|
+
return ft == 'ABIF' && fv >= 100
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(filename_or_io, options = {})
|
26
|
+
@data = {}
|
27
|
+
@data_params = {}
|
28
|
+
@named_data = {}
|
29
|
+
@some_counter = 1
|
30
|
+
|
31
|
+
@decipher = OpenSSL::Cipher.new('DES-CBC')
|
32
|
+
@decipher.key = "W\xB6\xBF\xBC\xFE\xBA1&" # [87, -74, -65, -68, -2, -70, 49, 38].pack('c*')
|
33
|
+
@decipher.iv = "\x8E\x129\x9C\aroZ" # [-114, 18, 57, -100, 7, 114, 111, 90].pack('c*')
|
34
|
+
|
35
|
+
io = nil
|
36
|
+
begin
|
37
|
+
io = filename_or_io.respond_to?(:seek) ? filename_or_io : ::File.open(filename_or_io, 'rb')
|
38
|
+
(@filetype, @fileversion) = io.read(6).unpack('A4S>')
|
39
|
+
raise IOError.new('Not an ABIF file') unless @filetype == 'ABIF' && @fileversion >= 100
|
40
|
+
header_dir_entry = unpack_dir_entry(io)
|
41
|
+
io.seek(header_dir_entry[:data_offset])
|
42
|
+
header_dir_entry[:num_elements].times do
|
43
|
+
dir_entry = unpack_dir_entry(io)
|
44
|
+
old_pos = io.pos
|
45
|
+
if dir_entry[:element_size] * dir_entry[:num_elements] > 4
|
46
|
+
io.seek(dir_entry[:data_offset])
|
47
|
+
else
|
48
|
+
io.seek(-8, IO::SEEK_CUR)
|
49
|
+
end
|
50
|
+
|
51
|
+
@data_params["#{dir_entry[:name]}_#{dir_entry[:number]}"] = [dir_entry[:element_type], dir_entry[:element_size], dir_entry[:num_elements], dir_entry[:data_size]]
|
52
|
+
@data["#{dir_entry[:name]}_#{dir_entry[:number]}"] = unpack_data(dir_entry[:element_type], dir_entry[:element_size], dir_entry[:num_elements], dir_entry[:data_size], io)
|
53
|
+
io.seek(old_pos)
|
54
|
+
end
|
55
|
+
rescue Exception => e
|
56
|
+
raise IOError.new "Error reding ABIF file: #{e}"
|
57
|
+
ensure
|
58
|
+
io.close unless io.nil? || !io.respond_to?(:close)
|
59
|
+
end
|
60
|
+
|
61
|
+
if options[:normalize] && options[:normalize] != 'none'
|
62
|
+
data_length = @data['DATA_1'].size
|
63
|
+
@data.keys.select{|key| key.include?('DATA_') && @data[key].size == data_length}.each do |key|
|
64
|
+
mean = 0.0
|
65
|
+
if options[:normalize] == 'head'
|
66
|
+
mean = @data[key][500..(500+[499,data_length].min)].inject(0.0){|t, datapoint| t + datapoint} / [499,data_length].min.to_f
|
67
|
+
elsif options[:normalize] == 'tail'
|
68
|
+
mean = @data[key][-500..-1].inject(0.0){|t, datapoint| t + datapoint} / 500.0
|
69
|
+
end
|
70
|
+
@data[key] = @data[key].map{|i| i - mean}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def some_counter
|
78
|
+
@some_counter = @some_counter + 1
|
79
|
+
end
|
80
|
+
|
81
|
+
def unpack_dir_entry(io)
|
82
|
+
dir_entry = {}
|
83
|
+
dir_entry[:name], dir_entry[:number], dir_entry[:element_type], dir_entry[:element_size], dir_entry[:num_elements], dir_entry[:data_size], dir_entry[:data_offset], dir_entry[:data_handle] = io.read(28).unpack('A4L>S>S>L>L>L>L>')
|
84
|
+
dir_entry
|
85
|
+
end
|
86
|
+
|
87
|
+
def unpack_data(type, size, num, data_size, io)
|
88
|
+
# TODO Checksum
|
89
|
+
# Fields: CkSm, CkSm-1, CkSm-2, CLst
|
90
|
+
# split by ':'
|
91
|
+
# Objects: java.util.Collections.synchronizedSortedSet/java.util.SortedSet/TreeSet/java.util.SortedSet
|
92
|
+
# MD5 BASE64Encoder "ABIFAdmin", "IdeABu++inghedsmiteCLI4S3", "81tingpH!sh1es", "eleMENT5ConsOLI45Dated", "AloysiusANdauGUST1NE"
|
93
|
+
data = io.read(data_size)
|
94
|
+
case type
|
95
|
+
when 0 # IllegalType -1-byte(s) wide
|
96
|
+
"illegal type 'IllegalType'(#{type})"
|
97
|
+
when 1 # Byte 1-byte(s) wide
|
98
|
+
data.unpack('C' * num)
|
99
|
+
when 2 # Char 1-byte(s) wide
|
100
|
+
data.unpack('C' * num)
|
101
|
+
when 3 # Word 2-byte(s) wide
|
102
|
+
data.unpack('S>' * num)
|
103
|
+
when 4 # Short 2-byte(s) wide
|
104
|
+
data.unpack('s>' * num)
|
105
|
+
when 5 # Long 4-byte(s) wide
|
106
|
+
data.unpack('l>' * num)
|
107
|
+
when 6 # Rational 8-byte(s) wide
|
108
|
+
struct = {}
|
109
|
+
struct[:numerator], struct[:denumerator] = data.unpack('l>l>' * num)
|
110
|
+
struct
|
111
|
+
when 7 # Float 4-byte(s) wide
|
112
|
+
data.unpack('g' * num)
|
113
|
+
when 8 # Double 8-byte(s) wide
|
114
|
+
data.unpack('G' * num)
|
115
|
+
when 9 # BCD 0-byte(s) wide
|
116
|
+
"unsupported type 'BCD'(#{type})"
|
117
|
+
when 10 # Date 4-byte(s) wide
|
118
|
+
struct = {}
|
119
|
+
struct[:year], struct[:month], struct[:day] = data.unpack('s>CC' * num)
|
120
|
+
struct
|
121
|
+
when 11 # Time 4-byte(s) wide
|
122
|
+
struct = {}
|
123
|
+
struct[:hour], struct[:minute], struct[:second], struct[:hsecond] = data.unpack('CCCC' * num)
|
124
|
+
struct
|
125
|
+
when 12 # Thumb 10-byte(s) wide
|
126
|
+
struct = {}
|
127
|
+
struct[:d], struct[:u], struct[:c], struct[:n] = data.unpack('l>l>CC' * num)
|
128
|
+
struct
|
129
|
+
when 13 # Boolean 1-byte(s) wide
|
130
|
+
data.unpack('C' * num).map{|x| x == 0 ? false : true}
|
131
|
+
when 14 # Point 4-byte(s) wide
|
132
|
+
struct = {}
|
133
|
+
struct[:v], struct[:h] = data.unpack('s>s>' * num)
|
134
|
+
struct
|
135
|
+
when 15 # Rect 8-byte(s) wide
|
136
|
+
struct = {}
|
137
|
+
struct[:top], struct[:left], struct[:bottom], struct[:right] = data.unpack('s>s>s>s>' * num)
|
138
|
+
struct
|
139
|
+
when 16 # VPoint 8-byte(s) wide
|
140
|
+
struct = {}
|
141
|
+
struct[:v], struct[:h] = data.unpack('l>l>' * num)
|
142
|
+
struct
|
143
|
+
when 17 # VRect 16-byte(s) wide
|
144
|
+
struct = {}
|
145
|
+
struct[:top], struct[:left], struct[:bottom], struct[:right] = data.unpack('l>l>l>l>' * num)
|
146
|
+
struct
|
147
|
+
when 18 # PString 1-byte(s) wide
|
148
|
+
data[1..data[0].unpack("C").first]
|
149
|
+
when 19 # CString 1-byte(s) wide
|
150
|
+
data[0..-2]
|
151
|
+
when 20 # Tag 8-byte(s) wide
|
152
|
+
struct = {}
|
153
|
+
struct[:name], struct[:number] = data.unpack('l>l>' * num)
|
154
|
+
struct
|
155
|
+
when 21 # DeltaLZWcompression 1-byte(s) wide
|
156
|
+
# TODO: What is a "DeltaLZWcompression" compression? Implement it the right way.
|
157
|
+
"unsupported compression 'DeltaLZWcompression'(#{type})"
|
158
|
+
when 22 # LZWcompression 1-byte(s) wide
|
159
|
+
unlzw(data.unpack('C' * size * num))
|
160
|
+
when 23 # Directory 28-byte(s) wide
|
161
|
+
unpack_dir_entry(data)
|
162
|
+
when 24 # UserType 1-byte(s) wide
|
163
|
+
"user type 'UserType'(#{type}) => #{num} elements of #{size}-byte wide struct: " << data.unpack('C' * size * num).join(', ')
|
164
|
+
when 25 # CustomUserType 1-byte(s) wide
|
165
|
+
"user type 'CustomUserType'(#{type}) => #{num} elements of #{size}-byte wide struct: " << data.unpack('C' * size * num).join(', ')
|
166
|
+
when 26 # IString 1-byte(s) wide
|
167
|
+
# TODO: What is an "IString"? Implement it the right way.
|
168
|
+
data
|
169
|
+
when 27 # compressedByte 1-byte(s) wide
|
170
|
+
decrypt(data).unpack('C' * data_size)
|
171
|
+
when 28 # compressedShort 1-byte(s) wide
|
172
|
+
decrypt(data).unpack('C' * (data_size / 2))
|
173
|
+
when 29 # compressedIString 1-byte(s) wide
|
174
|
+
# TODO: What is an "IString"? Implement it the right way.
|
175
|
+
decrypt(data)
|
176
|
+
when 30 # compressedChar 1-byte(s) wide
|
177
|
+
decrypt(data).unpack('C' * data_size)
|
178
|
+
when 31 # compressedLong 1-byte(s) wide
|
179
|
+
decrypt(data).unpack('l>' * (data_size / 4))
|
180
|
+
when 32 # compressedDouble 1-byte(s) wide
|
181
|
+
decrypt(data).unpack('G' * (data_size / 8))
|
182
|
+
when 33 # compressedCString 1-byte(s) wide
|
183
|
+
decrypt(data)[0..-2]
|
184
|
+
when 34 # compressedPString 1-byte(s) wide
|
185
|
+
decrypted = decrypt(data)
|
186
|
+
decrypted[1..decrypted[0].unpack("C").first]
|
187
|
+
when 35 # compressedFloat 1-byte(s) wide
|
188
|
+
decrypt(data).unpack('g' * (data_size / 4))
|
189
|
+
when 128 # deltaComp
|
190
|
+
# TODO: What is a "deltaComp" compression? Implement it the right way.
|
191
|
+
"unsupported compression 'deltaComp' data type '#{type}'"
|
192
|
+
when 256 # LZWComp
|
193
|
+
unlzw(data.unpack('C' * size * num))
|
194
|
+
when 384 # deltaLZW
|
195
|
+
# TODO: What is a "deltaLZW" compression? Implement it the right way.
|
196
|
+
"unsupported compression 'deltaLZW'(#{type})"
|
197
|
+
when 1024 # user
|
198
|
+
"user type 'user'(#{type}) => #{num} elements of #{size}-byte wide struct: " << data.unpack('C' * size * num).join(', ')
|
199
|
+
else
|
200
|
+
"unsupported type '#{type}': " << data.unpack('C' * size * num).join(', ')
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def inflate(compressed)
|
205
|
+
Zlib::Inflate.inflate compressed
|
206
|
+
end
|
207
|
+
|
208
|
+
def unlzw(compressed)
|
209
|
+
dict_size = 256
|
210
|
+
dictionary = Hash[ Array.new(dict_size) {|i| [i.chr, i.chr]} ]
|
211
|
+
|
212
|
+
w = result = compressed.shift
|
213
|
+
for k in compressed
|
214
|
+
if dictionary.has_key?(k)
|
215
|
+
entry = dictionary[k]
|
216
|
+
elsif k == dict_size
|
217
|
+
entry = w + w[0,1]
|
218
|
+
else
|
219
|
+
raise 'Bad compressed k: %s' % k
|
220
|
+
end
|
221
|
+
result += entry
|
222
|
+
|
223
|
+
dictionary[dict_size] = w + entry[0,1]
|
224
|
+
dict_size += 1
|
225
|
+
|
226
|
+
w = entry
|
227
|
+
end
|
228
|
+
result
|
229
|
+
end
|
230
|
+
|
231
|
+
def decrypt(encrypted)
|
232
|
+
@decipher.reset
|
233
|
+
@decipher.update(encrypted) + @decipher.final
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
data/lib/ABIF/version.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
2
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
3
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
4
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
5
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
6
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
7
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
8
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
9
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
10
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
11
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
12
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
13
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
14
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
15
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
16
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
17
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
18
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
19
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
20
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
21
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
22
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
23
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
24
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
25
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
26
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
27
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
28
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
29
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
30
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
31
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
32
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
33
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
34
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
35
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
36
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
37
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
38
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
39
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
40
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
41
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
42
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
43
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
44
|
+
NOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILENOTAVALIDABIFFILE
|
Binary file
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe ABIF::File do
|
4
|
+
describe 'omitting file/filename' do
|
5
|
+
it 'raises an Error' do
|
6
|
+
Proc.new { ABIF::File.new }.must_raise ArgumentError
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'invalid file/filehandle' do
|
11
|
+
it 'invalid file raises an Exception' do
|
12
|
+
Proc.new { ABIF::File.new('test/files/invalid.abif') }.must_raise IOError
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'non-existing file raises an Exception' do
|
16
|
+
Proc.new { ABIF::File.new('test/files/foo.abif') }.must_raise IOError
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'empty filehandle raises an Exception' do
|
20
|
+
Proc.new { ABIF::File.new(File.new) }.must_raise ArgumentError
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ABIF::File, 'valid filename' do
|
25
|
+
subject { ABIF::File.new('test/files/valid.abif') }
|
26
|
+
|
27
|
+
it 'is an instance of ABIF::File' do
|
28
|
+
subject.must_be_instance_of ABIF::File
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'filetype is ABIF' do
|
32
|
+
subject.filetype.must_equal 'ABIF'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'fileversion is 101' do
|
36
|
+
subject.fileversion.must_equal 101
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'data is a Hash' do
|
40
|
+
subject.data.must_be_kind_of Hash
|
41
|
+
end
|
42
|
+
|
43
|
+
{
|
44
|
+
'AEPt_1' => '329a2798ac4a2024f904a4900de7600d',
|
45
|
+
'AEPt_2' => '329a2798ac4a2024f904a4900de7600d',
|
46
|
+
'APFN_2' => '509a32e5f2979be945f61cddbd14622c',
|
47
|
+
'APXV_1' => '39c6844c921cf69656adaa2a8e4aea0c',
|
48
|
+
'APrN_1' => '509a32e5f2979be945f61cddbd14622c',
|
49
|
+
'APrV_1' => '3cf3aef9902754f1c9178e32f5fe1ddc',
|
50
|
+
'APrX_1' => '773e4cd95581ad061589066058e65d4f',
|
51
|
+
'ARTN_1' => '8d5162ca104fa7e79fe80fd92bb657fb',
|
52
|
+
'ASPF_1' => '35dba5d75538a9bbe0b4da4422759a0e',
|
53
|
+
'ASPt_1' => '220e850bfe79cb3526b375bc6dcdd2ef',
|
54
|
+
'ASPt_2' => '220e850bfe79cb3526b375bc6dcdd2ef',
|
55
|
+
'AUDT_1' => '49c8922d68864bb83c04879c1589a0fb',
|
56
|
+
'B1Pt_1' => 'af7e8bea94ff3c20159e249200b6aa18',
|
57
|
+
'B1Pt_2' => 'af7e8bea94ff3c20159e249200b6aa18',
|
58
|
+
'BCTS_1' => '162bb794a66800199501e1e9de7a15df',
|
59
|
+
'BufT_1' => '83a08dbe51340d001d2e7a3f8708e8cb',
|
60
|
+
'CCut_1' => 'b95b0b3bc23f39b3c04bc2baf211ba5b',
|
61
|
+
'CMNT_1' => '81bba32c7b86600386d96930ec17fda4',
|
62
|
+
'CTID_1' => '46f79adeafce95e4fdd7b6aebad1699e',
|
63
|
+
'CTNM_1' => '46f79adeafce95e4fdd7b6aebad1699e',
|
64
|
+
'CTOw_1' => 'c446a4c96a0fe001210b71144c2268f9',
|
65
|
+
'CTTL_1' => '74c70c8291e9dacf1935132d58229634',
|
66
|
+
'CpEP_1' => '35dba5d75538a9bbe0b4da4422759a0e',
|
67
|
+
'DATA_1' => 'c29a483afbeb83172305fb0803f3f264',
|
68
|
+
'DATA_2' => 'd9f5d923f13c66ff2385ee9cac1ba2f3',
|
69
|
+
'DATA_3' => 'e14a88b6353558b6af927de5ec1e070a',
|
70
|
+
'DATA_4' => '2b60b8f09786c6c182f53da105483bba',
|
71
|
+
'DATA_5' => '6f501928683d29942b95d5dad46e2e26',
|
72
|
+
'DATA_6' => 'f66e5d54b3606d9e060351c85a2ef733',
|
73
|
+
'DATA_7' => '7de240b0d5c835a9242555aaaa425d7a',
|
74
|
+
'DATA_8' => '272c59f929d32af7a1d655d175cf7a0e',
|
75
|
+
'DATA_9' => '66200730a3dc10020304032cc257dbd1',
|
76
|
+
'DATA_10' => '80238386cad29c86e1afc5d9a4d6622e',
|
77
|
+
'DATA_11' => '6d20453b6705c0144f954e9751b61c51',
|
78
|
+
'DATA_12' => '49061ea4bee661346a8d4ece6a606a3b',
|
79
|
+
'DCHT_1' => '8d5162ca104fa7e79fe80fd92bb657fb',
|
80
|
+
'DSam_1' => '35dba5d75538a9bbe0b4da4422759a0e',
|
81
|
+
'DySN_1' => 'c300e27b7c225652d4130f053f807199',
|
82
|
+
'Dye#_1' => 'e962e23c139e7252904b9221d9967442',
|
83
|
+
'DyeN_1' => 'b654f7796f95e5ed17096a82a0b28315',
|
84
|
+
'DyeN_2' => '207d360b49d1b72c0c35c89833757e5c',
|
85
|
+
'DyeN_3' => 'ac4b808acb1fc85fa0060bc92f489c69',
|
86
|
+
'DyeN_4' => '0ac0051af6ece5afeacf8e53e1dade59',
|
87
|
+
'DyeW_1' => 'f9639b0987d2ad3a3ae945ee29c889b4',
|
88
|
+
'DyeW_2' => '01df866ea9d6a730be6e319110ecfda0',
|
89
|
+
'DyeW_3' => 'c0280f103f34474ab0107746f80736fd',
|
90
|
+
'DyeW_4' => '47f2ba5a7a71c4646d8add9de01d8368',
|
91
|
+
'EPVt_1' => 'aea034f6800b624bf4d8d9fd4553d264',
|
92
|
+
'EVNT_1' => '10d4ece1db63d754b5ef1ba8fb635269',
|
93
|
+
'EVNT_2' => '9a81c64cb96fc6b7327bb2613c52e89d',
|
94
|
+
'EVNT_3' => 'fec688b3587dff8bb2c12a59cee0763e',
|
95
|
+
'EVNT_4' => '906341f47061764eb805b0b57b3cd7cc',
|
96
|
+
'FTab_1' => '21beecaab27020d9069dee9a570296d8',
|
97
|
+
'FVoc_1' => '139268d7ad20b68f72faa0b1691cac14',
|
98
|
+
'FWO__1' => '9f40a00e83bbaf678fe218b11f81d49e',
|
99
|
+
'Feat_1' => 'f9131fe168d95c26058ae03cff8e6be0',
|
100
|
+
'GTyp_1' => 'c7b375c0c538659369eee293b1cd8986',
|
101
|
+
'HCFG_1' => 'dbe992717239d8f63333a14fae4232c1',
|
102
|
+
'HCFG_2' => '9c0224cfb93aa409728cbac69fdf614b',
|
103
|
+
'HCFG_3' => '96cd52a8c96d12ba88c6ba36c316603d',
|
104
|
+
'HCFG_4' => 'fed17cd2cc23396408f8c2b480d71836',
|
105
|
+
'InSc_1' => '2a30f5f3b7d1a97cb6132480b992d984',
|
106
|
+
'InVt_1' => '423c57007341da0749aa1d8bb0da8042',
|
107
|
+
'LANE_1' => '6615ab6435d4f1da792f1e6fa230cb29',
|
108
|
+
'LIMS_1' => '6b3b0fa06550a54ba95f2e78dfb213b4',
|
109
|
+
'LNTD_1' => '8a8783242b7b77de148a06a0bab42ba9',
|
110
|
+
'LsrP_1' => '0a4f74e275e1168915d8d512ed22bf0c',
|
111
|
+
'MCHN_1' => 'ff90c90ed28916bb58eb2f56f425b41f',
|
112
|
+
'MODF_1' => '013f5a3ac5836a46be81dee59261f68d',
|
113
|
+
'MODL_1' => '59afde3cd75ce96556b9d5b3ce95fef5',
|
114
|
+
'NAVG_1' => '35dba5d75538a9bbe0b4da4422759a0e',
|
115
|
+
'NLNE_1' => '2375ef9e856b982a6f9e5b8fb903e6d7',
|
116
|
+
'NOIS_1' => '60afc12c44f69325eb1906a147339931',
|
117
|
+
'PBAS_1' => '214591fbf4e0c6032961ffb3dc685aaf',
|
118
|
+
'PBAS_2' => '214591fbf4e0c6032961ffb3dc685aaf',
|
119
|
+
'PCON_1' => '59cf9b876ec3410633cb72058af1cf8e',
|
120
|
+
'PCON_2' => '59cf9b876ec3410633cb72058af1cf8e',
|
121
|
+
'PDMF_1' => '94827116b0e6fec7abd084917c8cfc33',
|
122
|
+
'PDMF_2' => '94827116b0e6fec7abd084917c8cfc33',
|
123
|
+
'PLOC_1' => '87f2292a0f208ed70cb915c4d6c625e7',
|
124
|
+
'PLOC_2' => '87f2292a0f208ed70cb915c4d6c625e7',
|
125
|
+
'PSZE_1' => '2375ef9e856b982a6f9e5b8fb903e6d7',
|
126
|
+
'PTYP_1' => 'f75f3b63236ce233758cc898ebe835d0',
|
127
|
+
'PXLB_1' => 'f2577a6fc29b900fe7d4c6321346be48',
|
128
|
+
'RGNm_1' => '779dfa8b1b7a5cfd8063493b4bf2be46',
|
129
|
+
'RGOw_1' => 'b0b576a3a438583bd475a14acf06bf8b',
|
130
|
+
'RMXV_1' => '2f7bb230c70819aeb10b45a709bcf48f',
|
131
|
+
'RMdN_1' => '013f5a3ac5836a46be81dee59261f68d',
|
132
|
+
'RMdV_1' => '2f7bb230c70819aeb10b45a709bcf48f',
|
133
|
+
'RMdX_1' => '41b6d91073540a2a199bf9f089e11a29',
|
134
|
+
'RPrN_1' => '21d72202012057acf64ec7d3aa52ee42',
|
135
|
+
'RPrV_1' => '2f7bb230c70819aeb10b45a709bcf48f',
|
136
|
+
'RUND_1' => '21e7f6441ffe6ef6c36db98592ae0810',
|
137
|
+
'RUND_2' => '21e7f6441ffe6ef6c36db98592ae0810',
|
138
|
+
'RUND_3' => '21e7f6441ffe6ef6c36db98592ae0810',
|
139
|
+
'RUND_4' => '21e7f6441ffe6ef6c36db98592ae0810',
|
140
|
+
'RUNT_1' => '42a575cff8de9a296db610df9cff6f1f',
|
141
|
+
'RUNT_2' => '8647ea4a1090319b27562610d831172e',
|
142
|
+
'RUNT_3' => '1523ed7e16b541e809eb6acacf5f32c1',
|
143
|
+
'RUNT_4' => '337a52990fce3bea946d4fa60d0f51aa',
|
144
|
+
'Rate_1' => '9f1074af1ce98833fbf4775c5f3595cb',
|
145
|
+
'RunN_1' => '2048de7707e4fdc395175ce4784dce18',
|
146
|
+
'S/N%_1' => 'fbd3b15939b954654a38824ec1e82eb7',
|
147
|
+
'SCAN_1' => '329a2798ac4a2024f904a4900de7600d',
|
148
|
+
'SMED_1' => '0edefa708c51887ad9b3fbe1ea9e7e82',
|
149
|
+
'SMLt_1' => 'aed6e480b8aad696f3bb3a2781cd55d6',
|
150
|
+
'SMPL_1' => '172160c679614e93d5c07ef7b7a2441f',
|
151
|
+
'SPAC_1' => '3e58eb892f1ff04c1da6acf6509f976b',
|
152
|
+
'SPAC_2' => 'e991d1ef3f35a5da0b8b724490a6f21a',
|
153
|
+
'SPAC_3' => '3e58eb892f1ff04c1da6acf6509f976b',
|
154
|
+
'SVER_1' => 'a629005e3c810e8491172eebd622a57b',
|
155
|
+
'SVER_2' => 'cbd989d62be7257144760e24edeaf516',
|
156
|
+
'SVER_3' => '783e7db369d5e7d7d57e5c76a1dec609',
|
157
|
+
'Scal_1' => '8796ada1698c9940b7cf9264407731b1',
|
158
|
+
'Scan_1' => '329a2798ac4a2024f904a4900de7600d',
|
159
|
+
'TUBE_1' => 'aafe2f8af7d2109f20d5ae4c488bf1c6',
|
160
|
+
'Tmpr_1' => '1be08982f722684e69bdf6c5549d67ba',
|
161
|
+
'User_1' => 'c446a4c96a0fe001210b71144c2268f9',
|
162
|
+
'phAR_1' => '14a685bc2583777f837ed9d24798d915',
|
163
|
+
'phCH_1' => '89a93d4bcb2615549a98b93d2e2f5c96',
|
164
|
+
'phDY_1' => '7153f0402307a99a60929d7b5dcd886b',
|
165
|
+
'phQL_1' => 'e6cd5c7f942fc1c21557adbc97739b8c',
|
166
|
+
'phTR_1' => 'b95b0b3bc23f39b3c04bc2baf211ba5b',
|
167
|
+
'phTR_2' => '14a685bc2583777f837ed9d24798d915'
|
168
|
+
}.each do |key, md5|
|
169
|
+
it "MD5 of data['#{key}'] equals '#{md5}'" do
|
170
|
+
subject.data[key].wont_be_nil
|
171
|
+
Digest::MD5.hexdigest(subject.data[key].inspect).must_equal md5
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe 'supported?' do
|
177
|
+
it 'return false on unsupported file' do
|
178
|
+
ABIF::File.supported?('test/files/invalid.abif').must_equal false
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'return true on supported file' do
|
182
|
+
ABIF::File.supported?('test/files/valid.abif').must_equal true
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'raise an exception on non-existing file' do
|
186
|
+
Proc.new { ABIF::File.supported?('test/files/foo.abif') }.must_raise IOError
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ABIF
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sascha Willuweit
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: ABIF file format reader/parse/plotter.
|
70
|
+
email:
|
71
|
+
- s@rprojekt.org
|
72
|
+
executables:
|
73
|
+
- abifcli
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- ABIF.gemspec
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- bin/abifcli
|
84
|
+
- lib/ABIF.rb
|
85
|
+
- lib/ABIF/cli.rb
|
86
|
+
- lib/ABIF/file.rb
|
87
|
+
- lib/ABIF/version.rb
|
88
|
+
- test/files/invalid.abif
|
89
|
+
- test/files/valid.abif
|
90
|
+
- test/lib/ABIF/file_test.rb
|
91
|
+
- test/test_helper.rb
|
92
|
+
homepage: https://github.com/545ch4/ABIF
|
93
|
+
licenses:
|
94
|
+
- MIT
|
95
|
+
metadata: {}
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 2.0.6
|
113
|
+
signing_key:
|
114
|
+
specification_version: 4
|
115
|
+
summary: Handle/Parse/Plot ABIF (Applied Biosystems Genetic Analysis Data File Format)
|
116
|
+
FSA, AB1 and HID files.
|
117
|
+
test_files:
|
118
|
+
- test/files/invalid.abif
|
119
|
+
- test/files/valid.abif
|
120
|
+
- test/lib/ABIF/file_test.rb
|
121
|
+
- test/test_helper.rb
|