ABIF 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|