ms-msrun 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +3 -4
- data/Rakefile +20 -5
- data/bin/base64_to_array.rb +3 -4
- data/bin/ms_to_obiwarp.rb +6 -15
- data/bin/ms_to_search.rb +15 -22
- data/lib/lmat.rb +47 -53
- data/lib/ms/msrun.rb +98 -108
- data/lib/ms/msrun/axml/mzxml.rb +6 -8
- data/lib/ms/msrun/index.rb +130 -0
- data/lib/ms/msrun/mzxml.rb +12 -0
- data/lib/ms/msrun/nokogiri.rb +12 -0
- data/lib/ms/msrun/nokogiri/mzxml.rb +168 -0
- data/lib/ms/msrun/regexp/mzxml.rb +126 -0
- data/lib/ms/msrun/search.rb +25 -21
- data/lib/ms/msrun/sha1.rb +36 -0
- data/lib/ms/mzxml.rb +12 -0
- data/lib/ms/precursor.rb +3 -2
- data/lib/ms/precursor/lazy_parent.rb +28 -0
- data/lib/ms/scan.rb +2 -29
- data/lib/ms/spectrum/compare.rb +42 -2
- data/lib/ms/spectrum/filter.rb +1 -1
- data/spec/ms/msrun/index_spec.rb +60 -0
- data/spec/ms/msrun/scan_spec.rb +78 -0
- data/spec/ms/msrun/search_spec.rb +6 -7
- data/spec/ms/msrun/sha1_spec.rb +23 -0
- data/spec/ms/msrun_spec.rb +111 -3
- data/spec/ms/scan_spec.rb +2 -2
- data/spec/ms/spectrum/compare_spec.rb +13 -6
- data/spec/ms/spectrum/filter_spec.rb +3 -3
- metadata +42 -21
- data/lib/bsearch.rb +0 -120
- data/lib/ms/spectrum.rb +0 -373
data/README
CHANGED
@@ -4,7 +4,7 @@ A library for working with LC/MS runs.
|
|
4
4
|
|
5
5
|
== Examples
|
6
6
|
|
7
|
-
The following example will work on *mzXML*, *mzData* ( and *mzML* files
|
7
|
+
The following example will work on *mzXML*, *mzData* ( and *mzML* files in near future)!
|
8
8
|
|
9
9
|
require "ms/msrun"
|
10
10
|
|
@@ -55,8 +55,7 @@ The following example will work on *mzXML*, *mzData* ( and *mzML* files, shortly
|
|
55
55
|
gem install ms-msrun
|
56
56
|
|
57
57
|
The library currently relies on xmlparser (though LibXML is close to being
|
58
|
-
supported). After installation of ms-msrun (which
|
58
|
+
supported). After installation of ms-msrun (which should automatically install
|
59
59
|
`axml`) issue this command to get instructions on installing xmlparser:
|
60
60
|
|
61
|
-
ruby -rubygems -e 'require "axml"
|
62
|
-
puts AXML::Autoload.install_instructions(:xmlparser)'
|
61
|
+
ruby -rubygems -e 'require "axml"; puts AXML::Autoload.install_instructions(:xmlparser)'
|
data/Rakefile
CHANGED
@@ -35,11 +35,26 @@ Rake::RDocTask.new do |rd|
|
|
35
35
|
rd.options.push( *rdoc_options )
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
|
39
|
+
desc "Publish RDoc to RubyForge"
|
40
|
+
task :publish_rdoc => [:rdoc] do
|
41
|
+
require 'yaml'
|
42
|
+
|
43
|
+
config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
|
44
|
+
host = "#{config["username"]}@rubyforge.org"
|
45
|
+
|
46
|
+
rsync_args = "-v -c -r"
|
47
|
+
remote_dir = "/var/www/gforge-projects/mspire/projects/#{NAME}"
|
48
|
+
local_dir = "rdoc"
|
49
|
+
|
50
|
+
sh %{rsync #{rsync_args} #{local_dir}/ #{host}:#{remote_dir}}
|
41
51
|
end
|
42
52
|
|
53
|
+
#desc "create and upload docs to server"
|
54
|
+
#task :upload_docs => [:rdoc] do
|
55
|
+
# sh "scp -r #{rdoc_dir}/* jtprince@rubyforge.org:/var/www/gforge-projects/mspire/projects/ms-msrun/"
|
56
|
+
#end
|
57
|
+
|
43
58
|
###############################################
|
44
59
|
# TESTS
|
45
60
|
###############################################
|
@@ -77,12 +92,12 @@ gemspec = Gem::Specification.new do |t|
|
|
77
92
|
t.has_rdoc = true
|
78
93
|
t.authors = ["John Prince"]
|
79
94
|
t.files = dist_files
|
80
|
-
t.add_dependency '
|
95
|
+
t.add_dependency 'ms-core'
|
96
|
+
t.add_dependency 'nokogiri'
|
81
97
|
t.add_dependency 'runarray'
|
82
98
|
t.rdoc_options = rdoc_options
|
83
99
|
t.extra_rdoc_files = rdoc_extra_includes
|
84
100
|
t.executables = FL["bin/*"].map {|file| File.basename(file) }
|
85
|
-
t.requirements << 'xmlparser (preferrably) or libxml'
|
86
101
|
t.test_files = FL["spec/**/*_spec.rb"]
|
87
102
|
end
|
88
103
|
|
data/bin/base64_to_array.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
#!/usr/bin/ruby
|
1
2
|
|
2
|
-
require 'ms/
|
3
|
+
require 'ms/data/lazy_string'
|
3
4
|
|
4
5
|
if ARGV.size == 0
|
5
6
|
puts "usage: #{File.basename(__FILE__)} <base64_string>"
|
@@ -7,7 +8,5 @@ if ARGV.size == 0
|
|
7
8
|
exit
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
network_order = true
|
12
|
-
ar = Ms::Spectrum.base64_to_array(ARGV.shift, precision, network_order)
|
11
|
+
ar = Ms::Data::LazyString.new(ARGV.shift).to_a
|
13
12
|
puts "[ " + ar.join(", ") + " ]"
|
data/bin/ms_to_obiwarp.rb
CHANGED
@@ -21,8 +21,8 @@ opts = OptionParser.new do |op|
|
|
21
21
|
op.separator "(sums m/z values that round to the same bin)"
|
22
22
|
op.separator ""
|
23
23
|
op.on("--mz-inc N", Float, "m/z increment (def: 1.0)") {|n| opt[:mz_inc] = n.to_f}
|
24
|
-
op.on("--mz-start N", Float, "m/z start (
|
25
|
-
op.on("--mz-end N", Float, "m/z end (
|
24
|
+
op.on("--mz-start N", Float, "m/z start (otherwise auto)") {|n| opt[:start_mz] = n.to_f}
|
25
|
+
op.on("--mz-end N", Float, "m/z end (otherwise auto)") {|n| opt[:end_mz] = n.to_f}
|
26
26
|
op.on("--baseline N", Float, "value for missing indices (def: #{opt[:baseline]})") {|n| opt[:baseline] = n.to_f}
|
27
27
|
op.on("--ascii", "generates an lmata file instead") {opt[:ascii] = true}
|
28
28
|
op.on("-v", "--verbose") {$VERBOSE = true}
|
@@ -36,21 +36,12 @@ end
|
|
36
36
|
ARGV.each do |file|
|
37
37
|
Ms::Msrun.open(file) do |msrun|
|
38
38
|
mslevel = 1
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
:start_mz => start_mz,
|
43
|
-
:end_mz => end_mz,
|
44
|
-
|
45
|
-
:start_tm => times.first,
|
46
|
-
:end_tm => times.last,
|
47
|
-
:inc_tm => nil,
|
48
|
-
}
|
49
|
-
args.merge!(opt)
|
50
|
-
lmat = Ms::Msrun::Lmat.new.from_times_and_spectra(times, spectra, args)
|
39
|
+
lmat = Lmat.new
|
40
|
+
t = Time.now
|
41
|
+
lmat.from_msrun(msrun, opt)
|
51
42
|
ext = File.extname(file)
|
52
43
|
outfile = file.sub(/#{Regexp.escape(ext)}$/, opt[:newext])
|
53
|
-
if
|
44
|
+
if opt[:ascii]
|
54
45
|
outfile << "a"
|
55
46
|
lmat.print(outfile)
|
56
47
|
else
|
data/bin/ms_to_search.rb
CHANGED
@@ -1,37 +1,30 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
-
require '
|
4
|
+
require 'optparse'
|
5
|
+
require 'ms/msrun/search'
|
5
6
|
|
7
|
+
opts = OptionParser.new do |op|
|
8
|
+
op.banner = "usage: #{File.basename(__FILE__)} <file>.mzXML ..."
|
9
|
+
op.separator "outputs: <file>.mgf"
|
10
|
+
op.separator "[by default outputs .mgf file]"
|
6
11
|
|
7
|
-
|
8
|
-
class Ms::Msrun ; end
|
9
|
-
|
10
|
-
# Documentation here
|
11
|
-
class Ms::Msrun::Search < Tap::Task
|
12
|
-
|
13
|
-
#config :first_scan, 0, :short => 'F', &c.integer # first scan
|
14
|
-
#config :last_scan, 1e12, :short => 'L', &c.integer # last scan
|
15
|
-
## if not determined to be +1, then create these charge states
|
16
|
-
#config( :charge_states, [2,3], :short => 'c') {|v| v.split(',') }
|
17
|
-
#config :bottom_mh, 0, :short => 'B', &c.float # bottom MH+
|
18
|
-
#config :top_mh, -1.0, :short => 'T', &c.float # top MH+
|
19
|
-
#config :min_peaks, 0, :short => 'P', &c.integer # minimum peak count
|
20
|
-
#config :ms_levels, 2..-1, :short => 'M', &c.range # ms levels to export
|
12
|
+
end
|
21
13
|
|
14
|
+
if ARGV.size == 0
|
15
|
+
puts opts.to_s
|
16
|
+
exit
|
17
|
+
end
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
ARGV.each do |file|
|
20
|
+
Ms::Msrun.open(file) do |ms|
|
21
|
+
outfile = ms.to_mgf(file.sub(/\.mzxml/i, '.mgf'))
|
22
|
+
ms.to_mgf(outfile)
|
27
23
|
end
|
28
24
|
end
|
29
25
|
|
30
|
-
Ms::Msrun::Search.execute
|
31
|
-
|
32
26
|
# extract_msn.exe -M0.2 -B85 -T4500 -S0 -G1 -I35 -C0 -P2 -D output smallraw.RAW
|
33
27
|
|
34
|
-
|
35
28
|
#config :group_mass_tol, 1.4, :short => 'M', &c.float # prec. mass tolerance for grouping
|
36
29
|
#config :bottom_mw, 0.0, :short => 'B', &c.float # bottom MW for data file creation
|
37
30
|
#config :top_mw, 999999.0, :short => 'T', &c.float # top MW for data file creation
|
data/lib/lmat.rb
CHANGED
@@ -64,49 +64,65 @@ class Lmat
|
|
64
64
|
self
|
65
65
|
end
|
66
66
|
|
67
|
-
# converts
|
68
|
-
# times is an array (or VecI object)
|
69
|
-
# where each row = [mz,inten,mz,inten...]
|
67
|
+
# converts msrun object to a labeled matrix
|
70
68
|
# takes hash with symbols as keys
|
71
|
-
|
72
|
-
def from_times_and_spectra(times, spectra, args)
|
69
|
+
def from_msrun(msrun, args)
|
73
70
|
opt = {
|
74
|
-
:start_mz => 400.0,
|
75
|
-
:end_mz => 1500.0,
|
76
71
|
:inc_mz => 1.0,
|
77
72
|
:behave_mz => 'sum',
|
78
|
-
|
79
|
-
:start_tm => 0.0,
|
80
|
-
:end_tm => 3600.0,
|
81
|
-
:inc_tm => nil,
|
82
|
-
|
83
73
|
:baseline=> 0.0,
|
74
|
+
|
75
|
+
#:start_tm => 0.0,
|
76
|
+
#:end_tm => 3600.0,
|
77
|
+
#:inc_tm => nil,
|
78
|
+
|
79
|
+
#:start_mz => 400.0,
|
80
|
+
#:end_mz => 1500.0,
|
84
81
|
}
|
85
82
|
opt.merge!(args)
|
86
|
-
|
87
|
-
|
88
|
-
|
83
|
+
|
84
|
+
(st, en) = msrun.start_and_end_mz
|
85
|
+
unless st && en
|
86
|
+
msg = ["scanning spectrum for start and end m/z values"]
|
87
|
+
msg << "(use :start_mz and :end_mz options to avoid this)"
|
88
|
+
warn msg
|
89
|
+
(st, en) = msrun.start_and_end_mz_brute_force
|
90
|
+
end
|
91
|
+
opt[:start_mz] ||= st
|
92
|
+
opt[:end_mz] ||= en
|
93
|
+
|
94
|
+
#unless opt[:start_tm] then opt[:start_tm] = times.first end
|
95
|
+
#unless opt[:end_tm] then opt[:end_tm] = times.last end
|
96
|
+
|
89
97
|
if opt[:inc_tm]
|
90
98
|
raise NotImplementedError, "haven't implemented interpolation in ruby yet! (#{File.basename(__FILE__)}: #{__LINE__})"
|
91
99
|
else ## No interpolation
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
100
|
+
times = []
|
101
|
+
@nvec = nil
|
102
|
+
vecs = []
|
103
|
+
num_scans = msrun.scan_count
|
104
|
+
printf "Reading #{num_scans} spectra [.=100]" if $VERBOSE
|
105
|
+
spectrum_cnt = 0
|
106
|
+
msrun.each do |scan|
|
107
|
+
spectrum = scan.spectrum
|
108
|
+
times << scan.time
|
109
|
+
#(mz,inten) = spectrum_to_mz_and_inten(spectrum, VecD)
|
110
|
+
# TODO: Figure out a shallow copy here:
|
111
|
+
# perhaps we'll make spectra Vec objects by default in future and
|
112
|
+
# then we'd be set...
|
113
|
+
mzs = NArray.new(spectrum.mzs)
|
114
|
+
intens = NArray.new(spectrum.intensities)
|
115
|
+
(x,y) = mzs.inc_x(intens, opt[:start_mz], opt[:end_mz], opt[:inc_mz], opt[:baseline], opt[:behave_mz])
|
116
|
+
spectrum_cnt += 1
|
117
|
+
if spectrum_cnt % 100 == 0
|
118
|
+
printf "." if $VERBOSE ; $stdout.flush
|
107
119
|
end
|
108
|
-
@
|
120
|
+
@nvec ||= x # just need the first one for the x values
|
121
|
+
vecs << y
|
109
122
|
end
|
123
|
+
puts "DONE!" if $VERBOSE
|
124
|
+
@mvec = NArray.new(times)
|
125
|
+
@mat = vecs
|
110
126
|
end
|
111
127
|
self
|
112
128
|
end
|
@@ -124,28 +140,6 @@ class Lmat
|
|
124
140
|
other != nil && self.class == other.class && @nvec == other.nvec && @mvec == other.mvec && @mat == other.mat
|
125
141
|
end
|
126
142
|
|
127
|
-
# converts a single array of alternating m/z intensity values to two
|
128
|
-
# separate arrays
|
129
|
-
# (maybe implement in Ruby::Inline?)
|
130
|
-
# the answer is given in terms of arrs_as (object of class "arrs_as" must
|
131
|
-
# respond to "[]" and create a certain sized array with arrs_as.new(size))
|
132
|
-
def spectrum_to_mz_and_inten(spectrum, arrs_as=Array)
|
133
|
-
half_size = spectrum.size / 2
|
134
|
-
mzs = arrs_as.new(half_size)
|
135
|
-
intens = arrs_as.new(half_size)
|
136
|
-
mz = true
|
137
|
-
spectrum.each_index do |i|
|
138
|
-
if mz
|
139
|
-
mzs[i/2] = spectrum[i]
|
140
|
-
mz = false
|
141
|
-
else
|
142
|
-
mz = true
|
143
|
-
intens[(i-1)/2] = spectrum[i]
|
144
|
-
end
|
145
|
-
end
|
146
|
-
[mzs, intens]
|
147
|
-
end
|
148
|
-
|
149
143
|
def write(file=nil)
|
150
144
|
handle = $>
|
151
145
|
if file; handle = File.open(file, "wb") end
|
data/lib/ms/msrun.rb
CHANGED
@@ -3,9 +3,15 @@ require 'ms/scan'
|
|
3
3
|
require 'ms/precursor'
|
4
4
|
require 'ms/spectrum'
|
5
5
|
require 'ms/msrun/search'
|
6
|
+
require 'ms/msrun/index'
|
6
7
|
|
7
8
|
module Ms; end
|
8
9
|
class Ms::Msrun
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
#DEFAULT_PARSER = 'axml'
|
13
|
+
#DEFAULT_PARSER = 'regexp'
|
14
|
+
DEFAULT_PARSER = 'nokogiri'
|
9
15
|
|
10
16
|
# the retention time in seconds of the first scan (regardless of any
|
11
17
|
# meta-data written in the header)
|
@@ -13,8 +19,6 @@ class Ms::Msrun
|
|
13
19
|
# the retention time in seconds of the last scan (regardless of any
|
14
20
|
# meta-data written in the header)
|
15
21
|
attr_accessor :end_time
|
16
|
-
# an array of scans
|
17
|
-
attr_accessor :scans
|
18
22
|
|
19
23
|
# The filetype. Valid types (for parsing) are:
|
20
24
|
# :mzxml
|
@@ -39,6 +43,15 @@ class Ms::Msrun
|
|
39
43
|
# this will be nil.
|
40
44
|
attr_accessor :parent_location
|
41
45
|
|
46
|
+
# an array of doublets, [start_byte, length] for each scan element
|
47
|
+
attr_accessor :index
|
48
|
+
|
49
|
+
# holds the class that parses the file
|
50
|
+
attr_accessor :parser
|
51
|
+
|
52
|
+
# an array holding the scan numbers found in the run
|
53
|
+
attr_accessor :scan_nums
|
54
|
+
|
42
55
|
# Opens the filename
|
43
56
|
def self.open(filename, &block)
|
44
57
|
File.open(filename) {|io| block.call( self.new(io, filename) ) }
|
@@ -50,10 +63,13 @@ class Ms::Msrun
|
|
50
63
|
def initialize(io, filename=nil)
|
51
64
|
@scan_counts = nil
|
52
65
|
@filename = filename
|
53
|
-
@filetype, @version =
|
54
|
-
|
55
|
-
|
56
|
-
@
|
66
|
+
@filetype, @version = Ms::Msrun.filetype_and_version(io)
|
67
|
+
parser_klass = Ms::Msrun.get_parser(@filetype, @version)
|
68
|
+
|
69
|
+
@parser = parser_klass.new(self, io, @version)
|
70
|
+
@index = Ms::Msrun::Index.new(io)
|
71
|
+
@scan_nums = @index.scan_nums
|
72
|
+
@parser.parse_header(@index.header_length)
|
57
73
|
end
|
58
74
|
|
59
75
|
def parent_basename_noext
|
@@ -61,32 +77,59 @@ class Ms::Msrun
|
|
61
77
|
end
|
62
78
|
|
63
79
|
# returns each scan
|
64
|
-
|
65
|
-
|
80
|
+
# options:
|
81
|
+
# :spectrum => true | false (default is true)
|
82
|
+
# :precursor => true | false (default is true)
|
83
|
+
# :ms_level => Integer or Array return only scans of that level
|
84
|
+
# :reverse => true | false (default is false) goes backwards
|
85
|
+
def each_scan(parse_opts={}, &block)
|
86
|
+
ms_levels =
|
87
|
+
if msl = parse_opts[:ms_level]
|
88
|
+
if msl.is_a?(Integer) ; [msl]
|
89
|
+
else ; msl
|
90
|
+
end
|
91
|
+
end
|
92
|
+
snums = @index.scan_nums
|
93
|
+
snums = snums.reverse if parse_opts[:reverse]
|
94
|
+
snums.each do |scan_num|
|
95
|
+
if ms_levels
|
96
|
+
next unless ms_levels.include?(ms_level(scan_num))
|
97
|
+
end
|
98
|
+
block.call(scan(scan_num, parse_opts))
|
99
|
+
end
|
66
100
|
end
|
101
|
+
alias_method :each, :each_scan
|
67
102
|
|
68
103
|
# opens the file and yields each scan in the block
|
69
|
-
|
104
|
+
# see each_scan for parsing options
|
105
|
+
def self.foreach(filename, parse_opts={}, &block)
|
70
106
|
self.open(filename) do |obj|
|
71
|
-
obj.
|
107
|
+
obj.each_scan(parse_opts, &block)
|
72
108
|
end
|
73
109
|
end
|
74
110
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
by_level[scan.ms_level] = scan
|
79
|
-
end
|
80
|
-
by_level
|
111
|
+
# a very fast method to only query the ms_level of a scan
|
112
|
+
def ms_level(num)
|
113
|
+
@parser.parse_ms_level(@index[num].first, @index[num].last)
|
81
114
|
end
|
82
115
|
|
116
|
+
# returns a Ms::Scan object for the scan at that number
|
117
|
+
#
|
118
|
+
def scan(num, parse_opts={})
|
119
|
+
#@parser.parse_scan(*(@index[num]), parse_opts)
|
120
|
+
@parser.parse_scan(@index[num].first, @index[num].last, parse_opts)
|
121
|
+
end
|
122
|
+
|
123
|
+
#bracket_method = '[]'.to_sym
|
124
|
+
#alias_method bracket_method, :scan
|
125
|
+
|
83
126
|
# returns an array, whose indices provide the number of scans in each index level the ms_levels, [0] = all the scans, [1] = mslevel 1, [2] = mslevel 2,
|
84
127
|
# ...
|
85
128
|
def scan_counts
|
86
129
|
return @scan_counts if @scan_counts
|
87
130
|
ar = []
|
88
131
|
ar[0] = 0
|
89
|
-
|
132
|
+
each_scan do |sc|
|
90
133
|
level = sc.ms_level
|
91
134
|
unless ar[level]
|
92
135
|
ar[level] = 0
|
@@ -104,113 +147,57 @@ class Ms::Msrun
|
|
104
147
|
if mslevel == 0
|
105
148
|
@scan_count
|
106
149
|
else
|
107
|
-
|
108
|
-
scans.each do |sc|
|
109
|
-
if sc.ms_level == mslevel
|
110
|
-
num += 1
|
111
|
-
end
|
112
|
-
end
|
113
|
-
num
|
150
|
+
scan_counts[mslevel]
|
114
151
|
end
|
115
152
|
end
|
116
153
|
end
|
117
154
|
|
118
|
-
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
# set the initial hi_mz and lo_mz in any case
|
139
|
-
have_start_end_mz = false
|
140
|
-
scans.each do |sc|
|
141
|
-
if sc.ms_level == mslevel
|
142
|
-
if sc.start_mz && sc.end_mz
|
143
|
-
lo_mz = sc.start_mz
|
144
|
-
hi_mz = sc.end_mz
|
145
|
-
else
|
146
|
-
mz_ar = sc.spectrum.mzs
|
147
|
-
hi_mz = mz_ar.last
|
148
|
-
lo_mz = mz_ar.first
|
149
|
-
end
|
150
|
-
break
|
151
|
-
end
|
152
|
-
end
|
153
|
-
if have_start_end_mz
|
154
|
-
scans.each do |sc|
|
155
|
-
if sc.ms_level == mslevel
|
156
|
-
if sc.start_mz < lo_mz
|
157
|
-
lo_mz = sc.start_mz
|
158
|
-
end
|
159
|
-
if sc.end_mz > hi_mz
|
160
|
-
hi_mz = sc.end_mz
|
161
|
-
end
|
162
|
-
end
|
155
|
+
|
156
|
+
# returns [start_mz, end_mz] or [nil,nil] if unknown
|
157
|
+
def start_and_end_mz
|
158
|
+
scan = first(:ms_level => 1, :spectrum => false, :precursor => false)
|
159
|
+
[scan.start_mz, scan.end_mz]
|
160
|
+
end
|
161
|
+
|
162
|
+
# goes through every scan and gets the first and last m/z, then returns the
|
163
|
+
# max.ceil and min.floor
|
164
|
+
def start_and_end_mz_brute_force
|
165
|
+
first_scan = first(:ms_level => 1, :precursor => false)
|
166
|
+
first_mzs = first_scan.spectrum.mzs
|
167
|
+
|
168
|
+
lo_mz = first_mzs[0]
|
169
|
+
hi_mz = first_mzs[-1]
|
170
|
+
|
171
|
+
each_scan(:ms_level => 1, :precursor => false) do |sc|
|
172
|
+
mz_ar = sc.spectrum.mzs
|
173
|
+
if mz_ar.last > hi_mz
|
174
|
+
hi_mz = mz_ar.last
|
163
175
|
end
|
164
|
-
|
165
|
-
|
166
|
-
scans.each do |sc|
|
167
|
-
if sc.ms_level == mslevel
|
168
|
-
mz_ar = sc.spectrum.mzs
|
169
|
-
if mz_ar.last > hi_mz
|
170
|
-
hi_mz = mz_ar.last
|
171
|
-
end
|
172
|
-
if mz_ar.last < lo_mz
|
173
|
-
lo_mz = mz_ar.last
|
174
|
-
end
|
175
|
-
end
|
176
|
+
if mz_ar.last < lo_mz
|
177
|
+
lo_mz = mz_ar.last
|
176
178
|
end
|
177
179
|
end
|
178
180
|
[lo_mz.floor, hi_mz.ceil]
|
179
181
|
end
|
180
182
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
if ms_level == 0
|
187
|
-
times = @scans.map do |scan|
|
188
|
-
spectra << scan.spectrum
|
189
|
-
scan.time
|
190
|
-
end
|
191
|
-
[times, spectra]
|
192
|
-
else # choose a particular ms_level
|
193
|
-
times = []
|
194
|
-
@scans.each do |scan|
|
195
|
-
if ms_level == scan.ms_level
|
196
|
-
spectra << scan.spectrum
|
197
|
-
times << scan.time
|
198
|
-
end
|
199
|
-
end
|
200
|
-
[times, spectra]
|
183
|
+
def first(opts={})
|
184
|
+
the_first = nil
|
185
|
+
each_scan(opts) do |scan|
|
186
|
+
the_first = scan
|
187
|
+
break
|
201
188
|
end
|
189
|
+
the_first
|
202
190
|
end
|
203
|
-
end
|
204
|
-
|
205
191
|
|
206
|
-
|
207
|
-
|
208
|
-
|
192
|
+
def last(opts={})
|
193
|
+
opts[:reverse] = true
|
194
|
+
first(opts)
|
195
|
+
end
|
209
196
|
|
210
197
|
def self.get_parser(filetype, version)
|
211
|
-
require "ms/msrun
|
198
|
+
require "ms/msrun/#{DEFAULT_PARSER}/#{filetype}"
|
212
199
|
parser_class = filetype.to_s.capitalize
|
213
|
-
base_class = Ms::Msrun
|
200
|
+
base_class = Ms::Msrun.const_get( DEFAULT_PARSER.capitalize )
|
214
201
|
if base_class.const_defined? parser_class
|
215
202
|
base_class.const_get parser_class
|
216
203
|
else
|
@@ -247,6 +234,7 @@ module Ms::Msrun::Utils
|
|
247
234
|
end
|
248
235
|
end
|
249
236
|
|
237
|
+
|
250
238
|
Mzxml_regexp = /http:\/\/sashimi.sourceforge.net\/schema(_revision)?\/([\w\d_\.]+)/o
|
251
239
|
# 'http://sashimi.sourceforge.net/schema/MsXML.xsd' # version 1
|
252
240
|
# 'http://sashimi.sourceforge.net/schema_revision/mzXML_X.X' # others
|
@@ -258,6 +246,7 @@ module Ms::Msrun::Utils
|
|
258
246
|
if file_or_io.is_a? IO
|
259
247
|
io = file_or_io
|
260
248
|
found = nil
|
249
|
+
io.rewind
|
261
250
|
# Test for RAW file:
|
262
251
|
header = io.read(18).unpack(Raw_header_unpack_code).join
|
263
252
|
if header == 'Finnigan'
|
@@ -294,4 +283,5 @@ module Ms::Msrun::Utils
|
|
294
283
|
end
|
295
284
|
end
|
296
285
|
end
|
286
|
+
|
297
287
|
end
|