mspire 0.7.6 → 0.7.7
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/mzml_to_imzml +9 -0
- data/lib/mspire/cv/paramable.rb +46 -19
- data/lib/mspire/imzml/writer.rb +404 -0
- data/lib/mspire/imzml/writer/commandline.rb +109 -0
- data/lib/mspire/mzml/data_array.rb +33 -13
- data/lib/mspire/mzml/data_array_container_like.rb +0 -5
- data/lib/mspire/mzml/instrument_configuration.rb +1 -1
- data/lib/mspire/mzml/processing_method.rb +1 -1
- data/lib/mspire/mzml/referenceable_param_group.rb +2 -2
- data/lib/mspire/mzml/run.rb +1 -1
- data/lib/mspire/mzml/sample.rb +1 -1
- data/lib/mspire/mzml/scan.rb +1 -1
- data/lib/mspire/mzml/scan_list.rb +2 -2
- data/lib/mspire/mzml/scan_settings.rb +1 -1
- data/lib/mspire/mzml/software.rb +1 -1
- data/lib/mspire/mzml/source_file.rb +1 -1
- data/lib/mspire/mzml/spectrum.rb +2 -1
- data/mspire.gemspec +11 -2
- data/spec/mspire/imzml/writer_spec.rb +101 -0
- data/spec/testfiles/continuous_binary.tmp.ibd +0 -0
- data/spec/testfiles/mspire/imzml/continuous_binary_check.ibd +0 -0
- data/spec/testfiles/mspire/imzml/processed_binary_check.ibd +0 -0
- data/spec/testfiles/mspire/mzml/mspire_simulated.MSn.check.mzML +4 -4
- data/spec/testfiles/processed_binary.tmp.ibd +0 -0
- metadata +11 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.7.
|
1
|
+
0.7.7
|
data/bin/mzml_to_imzml
ADDED
data/lib/mspire/cv/paramable.rb
CHANGED
@@ -7,29 +7,48 @@ module Mspire
|
|
7
7
|
module CV
|
8
8
|
module Paramable
|
9
9
|
|
10
|
-
attr_accessor :
|
10
|
+
attr_accessor :cv_params
|
11
|
+
attr_accessor :user_params
|
12
|
+
attr_accessor :ref_param_groups
|
13
|
+
|
14
|
+
def params
|
15
|
+
cv_params + ref_param_groups.flat_map(&:params) + user_params
|
16
|
+
end
|
17
|
+
|
18
|
+
def accessionable_params
|
19
|
+
cv_params + ref_param_groups.flat_map(&:params)
|
20
|
+
end
|
21
|
+
|
22
|
+
def params_by_name
|
23
|
+
params.index_by &:name
|
24
|
+
end
|
25
|
+
|
26
|
+
def params_by_accession
|
27
|
+
accessionable_params.index_by &:accession
|
28
|
+
end
|
11
29
|
|
12
30
|
def initialize(opts={params: []})
|
31
|
+
@cv_params = []
|
32
|
+
@user_params = []
|
33
|
+
@ref_param_groups = []
|
13
34
|
describe_many!(opts[:params])
|
14
35
|
end
|
15
36
|
|
16
37
|
# cast may be something like :to_i or :to_f
|
17
38
|
def find_param_value_by_accession(accession, cast=nil)
|
18
|
-
param =
|
39
|
+
param = accessionable_params.find {|v| v.accession == accession }
|
19
40
|
if param
|
20
41
|
val = param.value
|
21
42
|
cast ? (val && val.send(cast)) : val
|
22
43
|
end
|
23
44
|
end
|
24
45
|
|
25
|
-
# cast may be something like :to_i or :to_f
|
26
46
|
def find_param_by_accession(accession)
|
27
|
-
|
47
|
+
accessionable_params.find {|v| v.accession == accession }
|
28
48
|
end
|
29
49
|
|
30
|
-
|
31
50
|
def param_exists_by_accession?(accession)
|
32
|
-
|
51
|
+
accessionable_params.any? {|v| v.accession == accession }
|
33
52
|
end
|
34
53
|
|
35
54
|
# takes an array of values, each of which is fed into describe!
|
@@ -57,11 +76,15 @@ module Mspire
|
|
57
76
|
#
|
58
77
|
# # given an XML
|
59
78
|
# obj.describe! xml_node.xpath('.//cvParam').first
|
79
|
+
#
|
80
|
+
# returns self
|
60
81
|
def describe!(*args)
|
61
|
-
|
82
|
+
return self if args.first.nil?
|
62
83
|
case (arg=args.first)
|
63
84
|
when String
|
64
|
-
@
|
85
|
+
@cv_params << Mspire::CV::Param[ *args ]
|
86
|
+
when Mspire::Mzml::ReferenceableParamGroup
|
87
|
+
@ref_param_groups << arg
|
65
88
|
when Nokogiri::XML::Node # a nokogiri node in particular
|
66
89
|
param =
|
67
90
|
case arg.name
|
@@ -73,25 +96,29 @@ module Mspire
|
|
73
96
|
if (unit_acc = arg[:unitAccession])
|
74
97
|
param.unit = ::CV::Param.new(arg[:unitCvRef], unit_acc, arg[:unitName])
|
75
98
|
end
|
76
|
-
@
|
99
|
+
@cv_params << param
|
77
100
|
when Nokogiri::XML::NodeSet
|
78
101
|
arg.each {|node| describe!(node) }
|
79
102
|
else
|
80
|
-
|
103
|
+
if arg.is_a?(Mspire::UserParam)
|
104
|
+
@user_params << arg
|
105
|
+
else
|
106
|
+
(@cv_params << arg) if arg
|
107
|
+
end
|
81
108
|
end
|
82
|
-
|
109
|
+
self
|
83
110
|
end
|
84
111
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
112
|
+
# iterates over @params and calls .to_xml on each object.
|
113
|
+
def to_xml(xml)
|
114
|
+
[:ref_param_groups, :cv_params, :user_params].each do |kind|
|
115
|
+
self.send(kind).each do |obj|
|
116
|
+
obj.to_xml(xml)
|
117
|
+
end
|
90
118
|
end
|
119
|
+
xml
|
91
120
|
end
|
92
|
-
xml
|
93
|
-
end
|
94
121
|
|
122
|
+
end
|
95
123
|
end
|
96
124
|
end
|
97
|
-
end
|
@@ -0,0 +1,404 @@
|
|
1
|
+
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'uuid'
|
4
|
+
require 'cv'
|
5
|
+
require 'mspire/mzml'
|
6
|
+
require 'mspire/mzml/spectrum'
|
7
|
+
require 'pathname'
|
8
|
+
require 'digest/sha1'
|
9
|
+
|
10
|
+
module Mspire end
|
11
|
+
|
12
|
+
module Mspire::Imzml
|
13
|
+
# array length (number of values), the offset (start in file in bytes),
|
14
|
+
# and the encoded length (in bytes).
|
15
|
+
DataArrayInfo = Struct.new :array_length, :offset, :encoded_length
|
16
|
+
|
17
|
+
class Writer
|
18
|
+
|
19
|
+
DEFAULTS = {
|
20
|
+
mz_data_type: :float,
|
21
|
+
mz_precision: 64,
|
22
|
+
intensity_data_type: :float,
|
23
|
+
intensity_precision: 32,
|
24
|
+
}
|
25
|
+
|
26
|
+
# Integer values (dtype=:int) may be stored with precision = 8, 16, 32,
|
27
|
+
# 64 . Floating point values may be stored as 32 or 64 bit precision.
|
28
|
+
# The byte order is always little endian (intel style).
|
29
|
+
#
|
30
|
+
# NOTE: the documentation is not clear whether they want signed or
|
31
|
+
# unsigned integers! Right now this outputs signed integers (my
|
32
|
+
# educated guess as to what is required)
|
33
|
+
def write_data_array(fh, values, dtype=:float, precision=32)
|
34
|
+
pack_code =
|
35
|
+
case dtype
|
36
|
+
when :float
|
37
|
+
precision == 64 ? 'E*' : 'e*'
|
38
|
+
when :int
|
39
|
+
# using signed!!!! (should these be unsigned??? NOT DOCUMENTED in
|
40
|
+
# imzml resources anywhere!)
|
41
|
+
case precision
|
42
|
+
when 8 ; 'c<*'
|
43
|
+
when 16 ; 's<*'
|
44
|
+
when 32 ; 'l<*'
|
45
|
+
when 64 ; 'q<*'
|
46
|
+
else
|
47
|
+
raise 'precision must be 8, 16, 32, or 64 for dtype==:int'
|
48
|
+
end
|
49
|
+
else
|
50
|
+
raise 'dtype must be :int or :float!'
|
51
|
+
end
|
52
|
+
fh.print values.pack(pack_code)
|
53
|
+
end
|
54
|
+
|
55
|
+
# returns an array of DataArrayInfo pairs
|
56
|
+
#
|
57
|
+
# These must be defined in the config hash with valid values (see
|
58
|
+
# write_data_array for what those are):
|
59
|
+
#
|
60
|
+
# :mz_data_type
|
61
|
+
# :mz_precision
|
62
|
+
# :intensity_data_type
|
63
|
+
# :intensity_precision
|
64
|
+
#
|
65
|
+
# Also recognizes :data_structure (:processed or :continuous). If
|
66
|
+
# :continuous, then the first spectrum is used to write the initial m/z
|
67
|
+
# and intensity pair, then in every spectrum after that the m/z data (if
|
68
|
+
# any) is ignored and only the intensities are written). The return is
|
69
|
+
# the same, the data info for each intensity is coupled with the m/z
|
70
|
+
# info from the first m/z data.
|
71
|
+
def write_binary(filename, spectra_iterator, config)
|
72
|
+
config = DEFAULTS.merge(config)
|
73
|
+
raise ":data_structure must be :continuous or :processed" unless [:processed, :continuous].include?(config[:data_structure])
|
74
|
+
(mz_dtype, mz_prec, int_dtype, int_prec) = config.values_at(:mz_data_type, :mz_precision, :intensity_data_type, :intensity_precision)
|
75
|
+
mz_prec_in_bytes = mz_prec / 8
|
76
|
+
int_prec_in_bytes = int_prec / 8
|
77
|
+
File.open(filename, 'wb') do |out|
|
78
|
+
out.print [config[:uuid]].pack("H*")
|
79
|
+
|
80
|
+
if config[:data_structure] == :continuous
|
81
|
+
# write the first m/z and get its info
|
82
|
+
mzs = spectra_iterator.peek.mzs
|
83
|
+
mz_info = Mspire::Imzml::DataArrayInfo.new mzs.size, out.pos, mzs.size * mz_prec_in_bytes
|
84
|
+
write_data_array(out, mzs, mz_dtype, mz_prec)
|
85
|
+
end
|
86
|
+
spectra_iterator.map do |spec|
|
87
|
+
|
88
|
+
if config[:data_structure] == :processed
|
89
|
+
mzs = spec.mzs
|
90
|
+
mz_info = Mspire::Imzml::DataArrayInfo.new mzs.size, out.pos, mzs.size * mz_prec_in_bytes
|
91
|
+
write_data_array(out, spec.mzs, mz_dtype, mz_prec)
|
92
|
+
end
|
93
|
+
|
94
|
+
ints = spec.intensities
|
95
|
+
int_info = Mspire::Imzml::DataArrayInfo.new ints.size, out.pos, ints.size * int_prec_in_bytes
|
96
|
+
write_data_array(out, spec.intensities, int_dtype, int_prec)
|
97
|
+
[mz_info, int_info]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# converts image related hash values to an array of loose describe!
|
103
|
+
# params
|
104
|
+
def image_hash_to_cvs(hash)
|
105
|
+
cvs = []
|
106
|
+
cvs << case hash[:data_structure].to_sym
|
107
|
+
when :processed ; 'IMS:1000031'
|
108
|
+
when :continuous ; 'IMS:1000030'
|
109
|
+
else ; raise ":data_structure must be :processed or :continuous"
|
110
|
+
end
|
111
|
+
|
112
|
+
cvs << case hash[:scan_pattern].to_sym
|
113
|
+
when :meandering ; 'IMS:1000410'
|
114
|
+
when :random ; 'IMS:1000412'
|
115
|
+
when :flyback ; 'IMS:1000413'
|
116
|
+
else ; raise ":scan_pattern must be :meandering, :random or :flyback"
|
117
|
+
end
|
118
|
+
|
119
|
+
cvs << case hash[:scan_type].to_sym
|
120
|
+
when :horizontal ; 'IMS:1000480'
|
121
|
+
when :vertical ; 'IMS:1000481'
|
122
|
+
else ; raise ":scan_type must be :horizontal or :vertical"
|
123
|
+
end
|
124
|
+
|
125
|
+
cvs << case hash[:linescan_direction].to_s
|
126
|
+
when 'left-right' ; 'IMS:1000402'
|
127
|
+
when 'right-left' ; 'IMS:1000403'
|
128
|
+
when 'bottom-up' ; 'IMS:1000400'
|
129
|
+
when 'top-down' ; 'IMS:1000401'
|
130
|
+
when 'none' ; 'IMS:1000404'
|
131
|
+
else ; raise ":linescan_direction unacceptable"
|
132
|
+
end
|
133
|
+
|
134
|
+
cvs << case hash[:linescan_sequence].to_s
|
135
|
+
when 'top-down' ; 'IMS:1000493'
|
136
|
+
when 'bottom-up' ; 'IMS:1000492'
|
137
|
+
when 'left-right' ; 'IMS:1000491'
|
138
|
+
when 'right-left' ; 'IMS:1000490'
|
139
|
+
else ; raise "linescan_sequence unacceptable"
|
140
|
+
end
|
141
|
+
|
142
|
+
max_pix_dims = hash[:max_dimensions_pixels].split(/x/i)
|
143
|
+
cvs.push *['IMS:1000042', 'IMS:1000043'].zip(max_pix_dims).to_a
|
144
|
+
|
145
|
+
real_dims = hash[:max_dimensions_microns].split(/x/i)
|
146
|
+
cvs.push *['IMS:1000044', 'IMS:1000045'].zip(real_dims).map {|pair| [*pair, "UO:0000017"] }
|
147
|
+
|
148
|
+
pix_dims = hash[:pixel_size].split(/x/i)
|
149
|
+
cvs.push *["IMS:1000046", "IMS:1000047"].zip(pix_dims).map {|pair| [*pair, "UO:0000017"] }
|
150
|
+
cvs
|
151
|
+
end
|
152
|
+
|
153
|
+
def experiment_hash_to_cvs(hash)
|
154
|
+
cvs = {
|
155
|
+
:matrix_solution_concentration => "MS:1000835",
|
156
|
+
:matrix_solution => "MS:1000834",
|
157
|
+
:solvent => 'IMS:1001211',
|
158
|
+
:solvent_flowrate => 'IMS:1001213',
|
159
|
+
:spray_voltage => 'IMS:1001212',
|
160
|
+
:target_material => 'IMS:10000202'
|
161
|
+
}.map do |key,cv_acc|
|
162
|
+
[cv_acc, hash[key]] if hash[key]
|
163
|
+
end.compact
|
164
|
+
|
165
|
+
mats = hash[:matrix_application_types]
|
166
|
+
if mats
|
167
|
+
app_types = mats.map do |typ|
|
168
|
+
case typ.to_s
|
169
|
+
when 'sprayed' ; 'MS:1000838'
|
170
|
+
when 'precoated' ; 'MS:1000839'
|
171
|
+
when 'printed' ; 'MS:1000837'
|
172
|
+
when 'drieddroplet' ; 'MS:1000836'
|
173
|
+
else ; raise "invalid matrix_application_type"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
cvs.push(*app_types)
|
177
|
+
end
|
178
|
+
cvs
|
179
|
+
end
|
180
|
+
|
181
|
+
# returns an array with x, y pairs in the correct order
|
182
|
+
# accounts for scan_pattern, scan_type, linescan_direction,
|
183
|
+
# linescan_sequence and shots_per_position
|
184
|
+
def x_y_positions(config)
|
185
|
+
(scan_pattern, scan_type, scan_direction, scan_sequence, shots_per_pos) = config.values_at(:scan_pattern, :scan_type, :linescan_direction, :linescan_sequence, :shots_per_position).map(&:to_s)
|
186
|
+
shots_per_pos = shots_per_pos.to_i
|
187
|
+
#puts "EXAMIN ARGS: "
|
188
|
+
#p [ scan_pattern, scan_type, scan_direction, scan_sequence, shots_per_pos, shots_per_pos]
|
189
|
+
|
190
|
+
# the true dimensions we need to work off come from the pixel dimensions.
|
191
|
+
(slen, plen) = config[:max_dimensions_pixels].split(/x/i).map(&:to_i)
|
192
|
+
|
193
|
+
flip = (scan_type == 'vertical')
|
194
|
+
plen, slen = slen, plen if flip
|
195
|
+
|
196
|
+
pindices = (1..plen).to_a # mindices if linescan_direction is 'horizontal'
|
197
|
+
sindices = (1..slen).to_a # nindices if linescan_direction is 'horizontal'
|
198
|
+
|
199
|
+
if flip
|
200
|
+
sindices.reverse! if scan_direction == 'bottom-top' || scan_direction == 'right-left'
|
201
|
+
pindices.reverse! if scan_sequence == 'right-left' || scan_sequence == 'bottom-top'
|
202
|
+
end
|
203
|
+
|
204
|
+
indices = pindices.map do |a|
|
205
|
+
row = sindices.map do |b|
|
206
|
+
flip ? [a,b] : [b,a]
|
207
|
+
end
|
208
|
+
sindices.reverse! if scan_pattern == 'meandering'
|
209
|
+
row
|
210
|
+
end.flatten(1)
|
211
|
+
|
212
|
+
indices.map {|pair| shots_per_pos.times.map { pair } }.flatten(1)
|
213
|
+
end
|
214
|
+
|
215
|
+
def create_file_description(source_files, config)
|
216
|
+
Mspire::Mzml::FileDescription.new do |fd|
|
217
|
+
|
218
|
+
fd.file_content = Mspire::Mzml::FileContent.new :params => [
|
219
|
+
'MS:1000579', # MS1 Spectrum
|
220
|
+
config[:profile] ? 'MS:1000128' : 'MS:1000127',
|
221
|
+
['IMS:1000080', "{"+config[:uuid_hyphenated]+"}"],
|
222
|
+
['IMS:1000091', config[:ibd_sha1]],
|
223
|
+
(config[:data_structure] == :processed) ? 'IMS:1000031' : 'IMS:1000030',
|
224
|
+
]
|
225
|
+
|
226
|
+
fd.source_files.replace(source_files)
|
227
|
+
if [:name, :organization, :address, :email].any? {|key| config[key] }
|
228
|
+
contact = Mspire::Mzml::Contact.new
|
229
|
+
[ [:name, 'MS:1000586'],
|
230
|
+
[:organization, 'MS:1000590'],
|
231
|
+
[:address, 'MS:1000587'],
|
232
|
+
[:email, 'MS:1000589']
|
233
|
+
].each do |key, accession|
|
234
|
+
contact.describe!(accession, config[key]) if config[key]
|
235
|
+
end
|
236
|
+
fd.contacts << contact
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def create_referenceable_params_by_id_hash
|
242
|
+
# m/z array and no compression (because we'll ref peaks in different
|
243
|
+
# file)
|
244
|
+
rparms = {
|
245
|
+
:mz_array => [
|
246
|
+
["MS:1000514", "MS:1000040"], # m/z array, units = m/z
|
247
|
+
"MS:1000576", # no compression
|
248
|
+
["IMS:1000101", true], # external data
|
249
|
+
'MS:1000523' # 64-bit float
|
250
|
+
],
|
251
|
+
:intensity_array => [
|
252
|
+
["MS:1000515", "MS:1000131"], # intensity array, units = number of counts
|
253
|
+
"MS:1000576", # no compression
|
254
|
+
["IMS:1000101", true], # external data
|
255
|
+
'MS:1000521' # 32-bit float
|
256
|
+
],
|
257
|
+
:scan1 => [
|
258
|
+
# this should probably be ascertained from the mzml file:
|
259
|
+
"MS:1000093", # increasing m/z scan
|
260
|
+
# "MS:1000095" # linear # <- this should probably be gathered
|
261
|
+
# from mzml (leave outfor now)
|
262
|
+
# could include the filter string here in future
|
263
|
+
],
|
264
|
+
:spectrum1 => [
|
265
|
+
"MS:1000579", # MS1 spectrum
|
266
|
+
["MS:1000511", 1], # ms level - default implementation uses 0 but I disagree...
|
267
|
+
"MS:1000127", # centroid spectrum
|
268
|
+
"MS:1000130" # <- positive scan
|
269
|
+
]}.map do |id, list|
|
270
|
+
Mspire::Mzml::ReferenceableParamGroup.new id, params: list
|
271
|
+
end
|
272
|
+
Hash[ rparms.map {|parm| [parm.id, parm]} ]
|
273
|
+
end
|
274
|
+
|
275
|
+
# mzml_filenames can each be a partial or relative path
|
276
|
+
# by default the file will write to the same directory and basename
|
277
|
+
#
|
278
|
+
# contact:
|
279
|
+
# :name => name of the person or organization
|
280
|
+
# :address => address of the person or organization
|
281
|
+
# :url => url of person or organization
|
282
|
+
# :email => email of person or organization
|
283
|
+
# :organization => home institution of contact
|
284
|
+
# experiment:
|
285
|
+
# :solvent => the solvent used
|
286
|
+
# :solvent_flowrate => flowrate of the solvent (ml/min)
|
287
|
+
# :spray_voltage => spray voltage in kV
|
288
|
+
# :target_material => the material the target is made of
|
289
|
+
# general:
|
290
|
+
# :omit_zeros => remove zero values
|
291
|
+
# :combine => use this outfile base name to combine files
|
292
|
+
# also works on single files to rename them.
|
293
|
+
# MUST be present if more than one mzml given.
|
294
|
+
# imaging:
|
295
|
+
# :data_structure => :processed or :continuous
|
296
|
+
# :scan_pattern => meandering random flyback
|
297
|
+
# :scan_type => horizontal or vertical
|
298
|
+
# :linescan_direction => scan_direction.join('|')
|
299
|
+
# :linescan_sequence => scan_sequence.join('|')
|
300
|
+
# :max_dimensions_pixels => maximum X by Y pixels (e.g. 300x100)
|
301
|
+
# :shots_per_position => number of spectra per position
|
302
|
+
# :pixel_size => X by Y of a single pixel in microns (μm)
|
303
|
+
# :max_dimensions_microns => maximum X by Y in microns (e.g. 25x20)
|
304
|
+
def write(mzml_filenames, config={})
|
305
|
+
|
306
|
+
base = config[:combine] || mzml_filenames.first.chomp(File.extname(mzml_filenames.first))
|
307
|
+
config[:imzml_filename] = base + ".imzML"
|
308
|
+
config[:ibd_filename] = base + ".ibd"
|
309
|
+
|
310
|
+
uuid_with_hyphens = UUID.new.generate
|
311
|
+
config[:uuid_hyphenated] = uuid_with_hyphens
|
312
|
+
config[:uuid] = uuid_with_hyphens.gsub('-','')
|
313
|
+
|
314
|
+
sourcefile_id_parallel_to_spectra = []
|
315
|
+
sourcefile_ids = []
|
316
|
+
all_spectra_iter = Enumerator.new do |yielder|
|
317
|
+
mzml_filenames.each_with_index do |mzml_filename,i|
|
318
|
+
sourcefile_id = "source_file_#{i}"
|
319
|
+
sourcefile_ids << sourcefile_id
|
320
|
+
Mspire::Mzml.open(mzml_filename) do |mzml|
|
321
|
+
mzml.each do |spec|
|
322
|
+
sourcefile_id_parallel_to_spectra << sourcefile_id
|
323
|
+
yielder << spec
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
data_info_pairs = write_binary(config[:ibd_filename], all_spectra_iter, config)
|
330
|
+
config[:ibd_sha1] = Digest::SHA1.hexdigest(IO.read(config[:ibd_filename]))
|
331
|
+
|
332
|
+
source_files = mzml_filenames.zip(sourcefile_ids).map do |mzml_filename, source_file_id|
|
333
|
+
sfile = Mspire::Mzml::SourceFile[ mzml_filename ]
|
334
|
+
sfile.id = source_file_id
|
335
|
+
sfile.describe! 'MS:1000584'
|
336
|
+
sfile.describe! 'MS:1000569', Digest::SHA1.hexdigest(IO.read(mzml_filename))
|
337
|
+
sfile
|
338
|
+
end
|
339
|
+
sourcefile_id_to_sourcefile = Hash[ source_files.group_by(&:id).map {|k,v| [k,v.first] } ]
|
340
|
+
|
341
|
+
imzml_obj = Mspire::Mzml.new do |imzml|
|
342
|
+
imzml.id = UUID.new.generate.gsub('-','')
|
343
|
+
imzml.cvs = Mspire::Mzml::CV::DEFAULT_CVS
|
344
|
+
|
345
|
+
imzml.file_description = create_file_description(source_files, config)
|
346
|
+
|
347
|
+
rparms_by_id = create_referenceable_params_by_id_hash
|
348
|
+
|
349
|
+
warn "using positive scan in every case but need to get this from original mzml!"
|
350
|
+
|
351
|
+
imzml.referenceable_param_groups = rparms_by_id.values
|
352
|
+
# skip sample list for now
|
353
|
+
mspire_software = Mspire::Mzml::Software.new( "mspire", Mspire::VERSION, params: ["MS:1000799"] )
|
354
|
+
imzml.software_list << mspire_software
|
355
|
+
|
356
|
+
scan_setting_params = image_hash_to_cvs( config )
|
357
|
+
scan_setting_params.push *experiment_hash_to_cvs( config )
|
358
|
+
imzml.scan_settings_list = [Mspire::Mzml::ScanSettings.new("scansettings1", params: scan_setting_params)]
|
359
|
+
|
360
|
+
warn 'todo: need to borrow instrumentConfiguration from original mzml'
|
361
|
+
|
362
|
+
default_instrument_config = Mspire::Mzml::InstrumentConfiguration.new("borrow_from_mzml")
|
363
|
+
warn 'todo: need to include default softare from mzml in default_instrument_config'
|
364
|
+
#default_instrument_config.software = Software.new( from the mzml file! )
|
365
|
+
imzml.instrument_configurations << default_instrument_config
|
366
|
+
|
367
|
+
# this is a generic 'file format conversion' but its the closest we
|
368
|
+
# have for mzml to imzml (which is really mzml to mzml)
|
369
|
+
data_processing_obj = Mspire::Mzml::DataProcessing.new('mzml_to_imzml')
|
370
|
+
data_processing_obj.processing_methods << Mspire::Mzml::ProcessingMethod.new(1, mspire_software, params: ['MS:1000530'] )
|
371
|
+
imzml.data_processing_list << data_processing_obj
|
372
|
+
|
373
|
+
warn "not implemented 'omit_zeros' yet"
|
374
|
+
# low intensity data point removal: "MS:1000594"
|
375
|
+
imzml.run = Mspire::Mzml::Run.new("run1", default_instrument_config) do |run|
|
376
|
+
spec_list = Mspire::Mzml::SpectrumList.new(data_processing_obj)
|
377
|
+
data_info_pairs.zip(x_y_positions(config), sourcefile_id_parallel_to_spectra).each_with_index do |(pair, xy, sourcefile_id),i|
|
378
|
+
# TODO: we should probably copy the id from the orig mzml (e.g.
|
379
|
+
# scan=1)
|
380
|
+
spectrum = Mspire::Mzml::Spectrum.new("spectrum#{i}", params: [rparms_by_id[:spectrum1]])
|
381
|
+
spectrum.source_file = sourcefile_id_to_sourcefile[sourcefile_id]
|
382
|
+
scan_list = Mspire::Mzml::ScanList.new(params: ['MS:1000795']) # no combination
|
383
|
+
scan = Mspire::Mzml::Scan.new( params: [rparms_by_id[:scan1], ["IMS:1000050", xy[0]], ["IMS:1000051", xy[1]]] )
|
384
|
+
scan.instrument_configuration = default_instrument_config
|
385
|
+
spectrum.scan_list = (scan_list << scan)
|
386
|
+
|
387
|
+
data_arrays = %w(mz intensity).zip(pair).map do |type, data_array_info|
|
388
|
+
rparmgroup = rparms_by_id[(type + "_array").to_sym]
|
389
|
+
data_array = Mspire::Mzml::DataArray.new
|
390
|
+
data_array.type = type
|
391
|
+
data_array.external = true
|
392
|
+
data_array.describe_many! [rparmgroup, *%w(IMS:1000103 IMS:1000102 IMS:1000104).zip(data_array_info).map.to_a]
|
393
|
+
data_array
|
394
|
+
end
|
395
|
+
spectrum.data_arrays = data_arrays
|
396
|
+
spec_list << spectrum
|
397
|
+
end
|
398
|
+
run.spectrum_list = spec_list
|
399
|
+
end # run
|
400
|
+
end # imzml
|
401
|
+
imzml_obj.to_xml(config[:imzml_filename])
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'mspire/imzml/writer'
|
4
|
+
require 'trollop'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
module Mspire
|
8
|
+
module Imzml
|
9
|
+
class Writer
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Mspire::Imzml::Writer::Commandline
|
15
|
+
|
16
|
+
def self.run(argv, progname=$0)
|
17
|
+
|
18
|
+
default_config = "config.yaml"
|
19
|
+
scan_patterns = %w(flyback meandering random)
|
20
|
+
scan_types = %w(horizontal vertical)
|
21
|
+
scan_direction = %w(left-right right-left bottom-up top-down none)
|
22
|
+
scan_sequence = %w(top-down bottom-up left-right right-left)
|
23
|
+
default_dims = '800x600'
|
24
|
+
default_pixel_size = '1x1'
|
25
|
+
matrix_application_types = %w(sprayed precoated printed drieddroplet)
|
26
|
+
|
27
|
+
parser = Trollop::Parser.new do
|
28
|
+
banner <<-EOS
|
29
|
+
usage: #{File.basename(progname)} [OPTIONS] <file>.mzML ..."
|
30
|
+
output: <file>.imzML and <file>.ibd
|
31
|
+
|
32
|
+
* imzML docs:
|
33
|
+
http://www.maldi-msi.org/index.php?option=com_content&view=article&id=187&Itemid=67
|
34
|
+
* explanation of vocabulary (followed here):
|
35
|
+
http://www.maldi-msi.org/index.php?option=com_content&view=article&id=193&Itemid=66
|
36
|
+
* github repository:
|
37
|
+
https://github.com/princelab/mzml_to_imzml
|
38
|
+
EOS
|
39
|
+
text "\ngeneral:"
|
40
|
+
opt :config, "read a config file for default values. Command line options overide those from the config file ", :type => :string
|
41
|
+
opt :print_config, "print current options to #{default_config} and exit"
|
42
|
+
opt :omit_zeros, "remove zero values"
|
43
|
+
opt :combine, "combine all files and set the base name of resulting imzML and ibd files", :type => String
|
44
|
+
opt :outfile, "use a specific basename for the resulting file. Acts like --combine for multiple files", :type => String
|
45
|
+
|
46
|
+
text "\nimaging:"
|
47
|
+
opt :continuous, "assumes m/z values are the same for every scan. The 'processed' storage format is used unless this flag is given."
|
48
|
+
opt :scan_pattern, scan_patterns.join('|'), :default => scan_patterns.first
|
49
|
+
opt :scan_type, scan_types.join('|'), :default => scan_types.first
|
50
|
+
opt :linescan_direction, scan_direction.join('|'), :default => scan_direction.first
|
51
|
+
opt :linescan_sequence, scan_sequence.join('|'), :default => scan_sequence.first
|
52
|
+
opt :max_dimensions_pixels, "maximum X by Y pixels (e.g. 300x100)", :default => default_dims
|
53
|
+
opt :shots_per_position, "number of spectra per position", :default => 1
|
54
|
+
opt :pixel_size, "X by Y of a single pixel in microns (μm)", :default => default_pixel_size
|
55
|
+
opt :max_dimensions_microns, "maximum X by Y in microns (e.g. 25x20)", :default => default_dims
|
56
|
+
|
57
|
+
text "\ncontact: "
|
58
|
+
opt :name, "name of the person or organization", :type => :string
|
59
|
+
opt :address, "address of the person or organization", :type => :string
|
60
|
+
opt :url, "url of person or organization", :type => :string
|
61
|
+
opt :email, "email of person or organization", :type => :string
|
62
|
+
opt :organization, "home institution of contact", :type => :string
|
63
|
+
|
64
|
+
text "\nDESI: "
|
65
|
+
opt :solvent, "the solvent used", :type => :string
|
66
|
+
opt :solvent_flowrate, "flowrate of the solvent (ml/min)", :type => :float
|
67
|
+
opt :spray_voltage, "spray voltage in kV", :type => :float
|
68
|
+
opt :target_material, "the material the target is made of", :type => :string
|
69
|
+
|
70
|
+
text "\nMALDI: "
|
71
|
+
opt :matrix_application_types, "#{matrix_application_types.join('|')} (comma separated)", :type => :string
|
72
|
+
opt :matrix_solution_concentration, "in grams per liter", :type => :float
|
73
|
+
opt :matrix_solution, "the chemical solution used as matrix (e.g., DHB)", :type => :string
|
74
|
+
|
75
|
+
# things to add: data types for m/z and intensity
|
76
|
+
# filters (cutoff / max # peaks, etc.)
|
77
|
+
# ms_level, etc.
|
78
|
+
end
|
79
|
+
|
80
|
+
opts = parser.parse(argv)
|
81
|
+
opts = Hash[YAML.load_file(opts[:config]).map {|k,v| [k.to_sym, v]}].merge(opts) if opts[:config]
|
82
|
+
|
83
|
+
opts[:combine] ||= opts.delete(:outfile)
|
84
|
+
|
85
|
+
if opts.delete(:print_config)
|
86
|
+
puts "writing defaults to: #{default_config}"
|
87
|
+
string_opts = Hash[ opts.map {|k,v| [k.to_s, v] } ]
|
88
|
+
%w(help).each {|key| string_opts.delete key }
|
89
|
+
string_opts.delete_if {|k,v| k =~ /_given$/ }
|
90
|
+
File.write(default_config, string_opts.to_yaml)
|
91
|
+
exit
|
92
|
+
end
|
93
|
+
|
94
|
+
if argv.size == 0
|
95
|
+
return parser.educate
|
96
|
+
end
|
97
|
+
|
98
|
+
opts[:data_structure] = (opts.delete(:continuous) ? :continuous : :processed)
|
99
|
+
opts[:matrix_application_types] = opts[:matrix_application_types].split(',') if opts[:matrix_application_types]
|
100
|
+
|
101
|
+
# prep args a little
|
102
|
+
writer = Mspire::Imzml::Writer.new
|
103
|
+
writer.write(argv, opts)
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
|
@@ -7,6 +7,8 @@ module Mspire
|
|
7
7
|
class DataArray < Array
|
8
8
|
alias_method :array_initialize, :initialize
|
9
9
|
include Mspire::CV::Paramable
|
10
|
+
alias_method :params_initialize, :initialize
|
11
|
+
alias_method :params_to_xml, :to_xml
|
10
12
|
|
11
13
|
DEFAULT_DTYPE = :float64
|
12
14
|
DEFAULT_COMPRESSION = true
|
@@ -18,11 +20,35 @@ module Mspire
|
|
18
20
|
int32: 'MS:1000519', # signed
|
19
21
|
}
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
+
def type=(arg)
|
24
|
+
all_accs = %w(MS:1000514 MS:1000515)
|
25
|
+
params.delete_if {|param| all_accs.include?(param.accession) } if params
|
26
|
+
case arg
|
27
|
+
when :mz
|
28
|
+
describe! all_accs[0] # , nil, "MS:1000040"
|
29
|
+
when :intensity
|
30
|
+
describe! all_accs[1] # , nil, "MS:1000131"
|
31
|
+
end
|
32
|
+
arg
|
33
|
+
end
|
34
|
+
|
35
|
+
def type
|
36
|
+
if params
|
37
|
+
if params.any? {|param| param.accession == 'MS:1000514' }
|
38
|
+
:mz
|
39
|
+
elsif params.any? {|param| param.accession == 'MS:1000515' }
|
40
|
+
:intensity
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# set this if the data is written to an external file (such as the ibd
|
46
|
+
# file for imzML files)
|
47
|
+
attr_accessor :external
|
23
48
|
|
24
49
|
def initialize(*args)
|
25
50
|
array_initialize(*args)
|
51
|
+
params_initialize
|
26
52
|
end
|
27
53
|
|
28
54
|
# returns a new Mspire::Mzml::DataArray object (an array)
|
@@ -72,7 +98,7 @@ module Mspire
|
|
72
98
|
#
|
73
99
|
# args:
|
74
100
|
# array-like set-like # where set-like responds to include?
|
75
|
-
# array-like
|
101
|
+
# array-like dtype=:float64, compression=true
|
76
102
|
def self.to_binary(array_ish, *args)
|
77
103
|
if args.first.respond_to?(:include?)
|
78
104
|
accessions = args.first
|
@@ -117,15 +143,11 @@ module Mspire
|
|
117
143
|
end
|
118
144
|
|
119
145
|
builder.binaryDataArray(encodedLength: encoded_length) do |bda_n|
|
120
|
-
|
121
|
-
unless
|
146
|
+
params_to_xml(bda_n)
|
147
|
+
unless self.external
|
122
148
|
Mspire::CV::Param[ DTYPE_TO_ACC[dtype] ].to_xml(bda_n)
|
123
149
|
Mspire::CV::Param[ compression ? 'MS:1000574' : 'MS:1000576' ].to_xml(bda_n)
|
124
|
-
|
125
|
-
accession = ( (@type == :mz) ? 'MS:1000514' : 'MS:1000515' )
|
126
|
-
Mspire::CV::Param[accession].to_xml(bda_n)
|
127
|
-
bda_n.binary(base64)
|
128
|
-
end
|
150
|
+
bda_n.binary(base64)
|
129
151
|
end
|
130
152
|
end
|
131
153
|
end
|
@@ -138,9 +160,7 @@ module Mspire
|
|
138
160
|
if data_ar.is_a?(Mspire::Mzml::DataArray)
|
139
161
|
data_ar
|
140
162
|
else
|
141
|
-
|
142
|
-
real_data_array.type = typ
|
143
|
-
real_data_array
|
163
|
+
Mspire::Mzml::DataArray.new(data_ar)
|
144
164
|
end
|
145
165
|
ar.type = typ unless ar.type
|
146
166
|
ar.to_xml(bdal_n)
|
@@ -26,11 +26,6 @@ module Mspire
|
|
26
26
|
# (optional) an array of Mspire::Mzml::DataArray
|
27
27
|
attr_accessor :data_arrays
|
28
28
|
|
29
|
-
def initialize(id, opts={params: []})
|
30
|
-
@id = id
|
31
|
-
describe_many!(opts[:params])
|
32
|
-
end
|
33
|
-
|
34
29
|
def default_array_length
|
35
30
|
if @data_arrays
|
36
31
|
if @data_arrays.first
|
@@ -14,7 +14,7 @@ module Mspire
|
|
14
14
|
|
15
15
|
def initialize(id, opts={params: []} )
|
16
16
|
@id = id
|
17
|
-
|
17
|
+
super(opts)
|
18
18
|
end
|
19
19
|
|
20
20
|
def to_xml(builder)
|
@@ -24,7 +24,7 @@ module Mspire
|
|
24
24
|
|
25
25
|
def to_xml_definition(builder)
|
26
26
|
builder.referenceableParamGroup(id: @id) do |fc_n|
|
27
|
-
|
27
|
+
params.each {|obj| obj.to_xml(fc_n) }
|
28
28
|
end
|
29
29
|
builder
|
30
30
|
end
|
data/lib/mspire/mzml/run.rb
CHANGED
@@ -30,7 +30,7 @@ module Mspire
|
|
30
30
|
def initialize(id, default_instrument_configuration, opts={params: []}, &block)
|
31
31
|
@id = id
|
32
32
|
@default_instrument_configuration = default_instrument_configuration
|
33
|
-
|
33
|
+
super(opts)
|
34
34
|
block.call(self) if block
|
35
35
|
end
|
36
36
|
|
data/lib/mspire/mzml/sample.rb
CHANGED
data/lib/mspire/mzml/scan.rb
CHANGED
@@ -13,13 +13,13 @@ module Mspire
|
|
13
13
|
include Mspire::CV::Paramable
|
14
14
|
|
15
15
|
def initialize(opts={params: []}, &block)
|
16
|
-
|
16
|
+
super(opts)
|
17
17
|
block.call(self) if block
|
18
18
|
end
|
19
19
|
|
20
20
|
def to_xml(builder)
|
21
21
|
builder.scanList(count: self.size) do |sl_n|
|
22
|
-
|
22
|
+
super(sl_n)
|
23
23
|
self.each do |scan|
|
24
24
|
scan.to_xml(sl_n)
|
25
25
|
end
|
data/lib/mspire/mzml/software.rb
CHANGED
data/lib/mspire/mzml/spectrum.rb
CHANGED
@@ -43,6 +43,7 @@ module Mspire
|
|
43
43
|
class Spectrum
|
44
44
|
include Mspire::SpectrumLike
|
45
45
|
include Mspire::Mzml::DataArrayContainerLike
|
46
|
+
alias_method :params_initialize, :initialize
|
46
47
|
|
47
48
|
# (optional) an Mspire::Mzml::SourceFile object
|
48
49
|
attr_accessor :source_file
|
@@ -144,7 +145,7 @@ module Mspire
|
|
144
145
|
#
|
145
146
|
def initialize(id, opts={params: []}, &block)
|
146
147
|
@id = id
|
147
|
-
|
148
|
+
params_initialize(opts)
|
148
149
|
block.call(self) if block
|
149
150
|
end
|
150
151
|
|
data/mspire.gemspec
CHANGED
@@ -5,13 +5,14 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "mspire"
|
8
|
-
s.version = "0.7.
|
8
|
+
s.version = "0.7.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["John T. Prince", "Simon Chiang"]
|
12
12
|
s.date = "2012-03-27"
|
13
13
|
s.description = "mass spectrometry proteomics, lipidomics, and tools, a rewrite of mspire, merging of ms-* gems"
|
14
14
|
s.email = "jtprince@gmail.com"
|
15
|
+
s.executables = ["mzml_to_imzml"]
|
15
16
|
s.extra_rdoc_files = [
|
16
17
|
"LICENSE",
|
17
18
|
"README.rdoc"
|
@@ -21,6 +22,7 @@ Gem::Specification.new do |s|
|
|
21
22
|
"README.rdoc",
|
22
23
|
"Rakefile",
|
23
24
|
"VERSION",
|
25
|
+
"bin/mzml_to_imzml",
|
24
26
|
"lib/core_ext/array/in_groups.rb",
|
25
27
|
"lib/cv.rb",
|
26
28
|
"lib/cv/param.rb",
|
@@ -56,6 +58,8 @@ Gem::Specification.new do |s|
|
|
56
58
|
"lib/mspire/ident/protein.rb",
|
57
59
|
"lib/mspire/ident/protein_group.rb",
|
58
60
|
"lib/mspire/ident/search.rb",
|
61
|
+
"lib/mspire/imzml/writer.rb",
|
62
|
+
"lib/mspire/imzml/writer/commandline.rb",
|
59
63
|
"lib/mspire/isotope.rb",
|
60
64
|
"lib/mspire/isotope/aa.rb",
|
61
65
|
"lib/mspire/isotope/distribution.rb",
|
@@ -128,6 +132,7 @@ Gem::Specification.new do |s|
|
|
128
132
|
"spec/mspire/ident/pepxml/search_hit/modification_info_spec.rb",
|
129
133
|
"spec/mspire/ident/pepxml_spec.rb",
|
130
134
|
"spec/mspire/ident/protein_group_spec.rb",
|
135
|
+
"spec/mspire/imzml/writer_spec.rb",
|
131
136
|
"spec/mspire/isotope/aa_spec.rb",
|
132
137
|
"spec/mspire/isotope/distribution_spec.rb",
|
133
138
|
"spec/mspire/isotope_spec.rb",
|
@@ -151,8 +156,11 @@ Gem::Specification.new do |s|
|
|
151
156
|
"spec/mspire_spec.rb",
|
152
157
|
"spec/obo_spec.rb",
|
153
158
|
"spec/spec_helper.rb",
|
159
|
+
"spec/testfiles/continuous_binary.tmp.ibd",
|
154
160
|
"spec/testfiles/mspire/ident/peptide/db/uni_11_sp_tr.fasta",
|
155
161
|
"spec/testfiles/mspire/ident/peptide/db/uni_11_sp_tr.msd_clvg2.min_aaseq4.yml",
|
162
|
+
"spec/testfiles/mspire/imzml/continuous_binary_check.ibd",
|
163
|
+
"spec/testfiles/mspire/imzml/processed_binary_check.ibd",
|
156
164
|
"spec/testfiles/mspire/mzml/j24z.idx_comp.3.mzML",
|
157
165
|
"spec/testfiles/mspire/mzml/mspire_simulated.MSn.check.mzML",
|
158
166
|
"spec/testfiles/mspire/mzml/openms.noidx_nocomp.12.mzML",
|
@@ -175,7 +183,8 @@ Gem::Specification.new do |s|
|
|
175
183
|
"spec/testfiles/mspire/quant/pdcd5_lfq_tabdel.txt_qspecgp",
|
176
184
|
"spec/testfiles/mspire/quant/remove_rest_of_proteins.rb",
|
177
185
|
"spec/testfiles/mspire/quant/unlog_transform.rb",
|
178
|
-
"spec/testfiles/plms1/output.key"
|
186
|
+
"spec/testfiles/plms1/output.key",
|
187
|
+
"spec/testfiles/processed_binary.tmp.ibd"
|
179
188
|
]
|
180
189
|
s.homepage = "http://github.com/princelab/mspire"
|
181
190
|
s.licenses = ["MIT"]
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'mspire/imzml/writer'
|
4
|
+
require 'mspire/spectrum'
|
5
|
+
|
6
|
+
describe Mspire::Imzml::Writer do
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
@spectra = [
|
10
|
+
Mspire::Spectrum.new([[1,2,3],[4,5,6]]),
|
11
|
+
Mspire::Spectrum.new([[1,2,3],[4,5,6]]),
|
12
|
+
Mspire::Spectrum.new([[1,2,3],[4,5,6]]),
|
13
|
+
]
|
14
|
+
@config = {
|
15
|
+
uuid: "d097f8103a8e012f2b130024e8b4cdae",
|
16
|
+
mz_data_type: :float,
|
17
|
+
mz_precision: 32,
|
18
|
+
# just for fun, use floats for m/z and ints for intensities
|
19
|
+
intensity_data_type: :int,
|
20
|
+
intensity_precision: 32,
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'has an iterator that creates the proper x and y positions' do
|
25
|
+
#config = { :scan_pattern => 'meandering', :scan_type => 'horizontal', :linescan_direction => 'left-right', :linescan_sequence => 'top-down', :max_dimensions_pixels => '3x2', :pixel_size => '2x2', :max_dimensions_microns => '6x4', :shots_per_position => 2 }
|
26
|
+
writer = Mspire::Imzml::Writer.new
|
27
|
+
testing = {
|
28
|
+
|
29
|
+
%w(flyback horizontal left-right top-bottom) => [[1, 1], [1, 1], [2, 1], [2, 1], [3, 1], [3, 1], [1, 2], [1, 2], [2, 2], [2, 2], [3, 2], [3, 2]],
|
30
|
+
%w(flyback horizontal left-right bottom-top) => [[1, 1], [1, 1], [2, 1], [2, 1], [3, 1], [3, 1], [1, 2], [1, 2], [2, 2], [2, 2], [3, 2], [3, 2]],
|
31
|
+
%w(flyback horizontal right-left bottom-top) => [[1, 1], [1, 1], [2, 1], [2, 1], [3, 1], [3, 1], [1, 2], [1, 2], [2, 2], [2, 2], [3, 2], [3, 2]],
|
32
|
+
%w(flyback horizontal right-left top-bottom) => [[1, 1], [1, 1], [2, 1], [2, 1], [3, 1], [3, 1], [1, 2], [1, 2], [2, 2], [2, 2], [3, 2], [3, 2]],
|
33
|
+
%w(meandering horizontal left-right top-bottom) => [[1, 1], [1, 1], [2, 1], [2, 1], [3, 1], [3, 1], [3, 2], [3, 2], [2, 2], [2, 2], [1, 2], [1, 2]],
|
34
|
+
%w(meandering horizontal left-right bottom-top) => [[1, 1], [1, 1], [2, 1], [2, 1], [3, 1], [3, 1], [3, 2], [3, 2], [2, 2], [2, 2], [1, 2], [1, 2]],
|
35
|
+
%w(meandering horizontal right-left bottom-top) => [[1, 1], [1, 1], [2, 1], [2, 1], [3, 1], [3, 1], [3, 2], [3, 2], [2, 2], [2, 2], [1, 2], [1, 2]],
|
36
|
+
%w(meandering horizontal right-left top-bottom) => [[1, 1], [1, 1], [2, 1], [2, 1], [3, 1], [3, 1], [3, 2], [3, 2], [2, 2], [2, 2], [1, 2], [1, 2]],
|
37
|
+
%w(flyback vertical top-bottom left-right) => [[1, 1], [1, 1], [1, 2], [1, 2], [2, 1], [2, 1], [2, 2], [2, 2], [3, 1], [3, 1], [3, 2], [3, 2]],
|
38
|
+
%w(flyback vertical bottom-top right-left) => [[3, 2], [3, 2], [3, 1], [3, 1], [2, 2], [2, 2], [2, 1], [2, 1], [1, 2], [1, 2], [1, 1], [1, 1]],
|
39
|
+
%w(flyback vertical bottom-top left-right) => [[1, 2], [1, 2], [1, 1], [1, 1], [2, 2], [2, 2], [2, 1], [2, 1], [3, 2], [3, 2], [3, 1], [3, 1]],
|
40
|
+
%w(flyback vertical top-bottom right-left) => [[3, 1], [3, 1], [3, 2], [3, 2], [2, 1], [2, 1], [2, 2], [2, 2], [1, 1], [1, 1], [1, 2], [1, 2]],
|
41
|
+
%w(meandering vertical top-bottom left-right) => [[1, 1], [1, 1], [1, 2], [1, 2], [2, 2], [2, 2], [2, 1], [2, 1], [3, 1], [3, 1], [3, 2], [3, 2]],
|
42
|
+
%w(meandering vertical bottom-top right-left) => [[3, 2], [3, 2], [3, 1], [3, 1], [2, 1], [2, 1], [2, 2], [2, 2], [1, 2], [1, 2], [1, 1], [1, 1]],
|
43
|
+
%w(meandering vertical bottom-top left-right) => [[1, 2], [1, 2], [1, 1], [1, 1], [2, 1], [2, 1], [2, 2], [2, 2], [3, 2], [3, 2], [3, 1], [3, 1]],
|
44
|
+
%w(meandering vertical top-bottom right-left) => [[3, 1], [3, 1], [3, 2], [3, 2], [2, 2], [2, 2], [2, 1], [2, 1], [1, 1], [1, 1], [1, 2], [1, 2]]
|
45
|
+
}
|
46
|
+
cats = %w(scan_pattern scan_type linescan_direction linescan_sequence).map(&:to_sym)
|
47
|
+
testing. each do |(configs, expected)|
|
48
|
+
config = Hash[ cats.zip(configs).map.to_a ]
|
49
|
+
config[:max_dimensions_pixels] = '3x2'
|
50
|
+
config[:shots_per_position] = 2
|
51
|
+
writer.x_y_positions(config).should == expected
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'writes :processed binary file with spectra and returns DataArrayInfo objects' do
|
56
|
+
expected_file = TESTFILES + "/mspire/imzml/processed_binary_check.ibd"
|
57
|
+
write_to = TESTFILES + "/mspire/imzml/processed_binary.tmp.ibd"
|
58
|
+
array = subject.write_binary(write_to, @spectra.each, @config.merge( {:data_structure => :processed} ))
|
59
|
+
IO.read(write_to).should == IO.read(expected_file)
|
60
|
+
array.should be_an(Array)
|
61
|
+
length = 3
|
62
|
+
offsets = (16..76).step(12)
|
63
|
+
encoded_length = 12
|
64
|
+
|
65
|
+
array.each do |info_pair|
|
66
|
+
info_pair.each do |obj|
|
67
|
+
obj.should be_a(Mspire::Imzml::DataArrayInfo)
|
68
|
+
obj.length.should == length
|
69
|
+
obj.encoded_length.should == encoded_length
|
70
|
+
obj.offset.should == offsets.next
|
71
|
+
end
|
72
|
+
end
|
73
|
+
File.unlink(write_to) if File.exist?(write_to)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'writes :continuous binary file with spectra and returns DataArrayInfo objects' do
|
77
|
+
expected_file = TESTFILES + "/mspire/imzml/continuous_binary_check.ibd"
|
78
|
+
write_to = TESTFILES + "/mspire/imzml/continuous_binary.tmp.ibd"
|
79
|
+
array = subject.write_binary(write_to, @spectra.each, @config.merge( {:data_structure => :continuous} ))
|
80
|
+
IO.read(write_to).should == IO.read(expected_file)
|
81
|
+
array.should be_an(Array)
|
82
|
+
|
83
|
+
length = 3
|
84
|
+
offsets = (28..52).step(12)
|
85
|
+
encoded_length = 12
|
86
|
+
first_offset = 16
|
87
|
+
|
88
|
+
array.each do |info_pair|
|
89
|
+
info_pair.each do |obj|
|
90
|
+
obj.should be_a(Mspire::Imzml::DataArrayInfo)
|
91
|
+
obj.length.should == length
|
92
|
+
obj.encoded_length.should == encoded_length
|
93
|
+
end
|
94
|
+
info_pair.first.offset.should == first_offset
|
95
|
+
info_pair.last.offset.should == offsets.next
|
96
|
+
end
|
97
|
+
File.unlink(write_to) if File.exist?(write_to)
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
@@ -40,15 +40,15 @@
|
|
40
40
|
</scanList>
|
41
41
|
<binaryDataArrayList count="2">
|
42
42
|
<binaryDataArray encodedLength="28">
|
43
|
+
<cvParam cvRef="MS" accession="MS:1000514" name="m/z array"/>
|
43
44
|
<cvParam cvRef="MS" accession="MS:1000523" name="64-bit float"/>
|
44
45
|
<cvParam cvRef="MS" accession="MS:1000574" name="zlib compression"/>
|
45
|
-
<cvParam cvRef="MS" accession="MS:1000514" name="m/z array"/>
|
46
46
|
<binary>eJxjYACBD/YMEOAAoTgcABe3Abg=</binary>
|
47
47
|
</binaryDataArray>
|
48
48
|
<binaryDataArray encodedLength="28">
|
49
|
+
<cvParam cvRef="MS" accession="MS:1000515" name="intensity array"/>
|
49
50
|
<cvParam cvRef="MS" accession="MS:1000523" name="64-bit float"/>
|
50
51
|
<cvParam cvRef="MS" accession="MS:1000574" name="zlib compression"/>
|
51
|
-
<cvParam cvRef="MS" accession="MS:1000515" name="intensity array"/>
|
52
52
|
<binary>eJxjYAABAQcwxSACpSUcAAjwAP0=</binary>
|
53
53
|
</binaryDataArray>
|
54
54
|
</binaryDataArrayList>
|
@@ -73,15 +73,15 @@
|
|
73
73
|
</precursorList>
|
74
74
|
<binaryDataArrayList count="2">
|
75
75
|
<binaryDataArray encodedLength="28">
|
76
|
+
<cvParam cvRef="MS" accession="MS:1000514" name="m/z array"/>
|
76
77
|
<cvParam cvRef="MS" accession="MS:1000523" name="64-bit float"/>
|
77
78
|
<cvParam cvRef="MS" accession="MS:1000574" name="zlib compression"/>
|
78
|
-
<cvParam cvRef="MS" accession="MS:1000514" name="m/z array"/>
|
79
79
|
<binary>eJxjYACBD/YMEOAAoXgcABe/Abw=</binary>
|
80
80
|
</binaryDataArray>
|
81
81
|
<binaryDataArray encodedLength="28">
|
82
|
+
<cvParam cvRef="MS" accession="MS:1000515" name="intensity array"/>
|
82
83
|
<cvParam cvRef="MS" accession="MS:1000523" name="64-bit float"/>
|
83
84
|
<cvParam cvRef="MS" accession="MS:1000574" name="zlib compression"/>
|
84
|
-
<cvParam cvRef="MS" accession="MS:1000515" name="intensity array"/>
|
85
85
|
<binary>eJxjYAABEQcwxSABpUUcAAlYAQE=</binary>
|
86
86
|
</binaryDataArray>
|
87
87
|
</binaryDataArrayList>
|
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mspire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -175,7 +175,8 @@ dependencies:
|
|
175
175
|
description: mass spectrometry proteomics, lipidomics, and tools, a rewrite of mspire,
|
176
176
|
merging of ms-* gems
|
177
177
|
email: jtprince@gmail.com
|
178
|
-
executables:
|
178
|
+
executables:
|
179
|
+
- mzml_to_imzml
|
179
180
|
extensions: []
|
180
181
|
extra_rdoc_files:
|
181
182
|
- LICENSE
|
@@ -185,6 +186,7 @@ files:
|
|
185
186
|
- README.rdoc
|
186
187
|
- Rakefile
|
187
188
|
- VERSION
|
189
|
+
- bin/mzml_to_imzml
|
188
190
|
- lib/core_ext/array/in_groups.rb
|
189
191
|
- lib/cv.rb
|
190
192
|
- lib/cv/param.rb
|
@@ -220,6 +222,8 @@ files:
|
|
220
222
|
- lib/mspire/ident/protein.rb
|
221
223
|
- lib/mspire/ident/protein_group.rb
|
222
224
|
- lib/mspire/ident/search.rb
|
225
|
+
- lib/mspire/imzml/writer.rb
|
226
|
+
- lib/mspire/imzml/writer/commandline.rb
|
223
227
|
- lib/mspire/isotope.rb
|
224
228
|
- lib/mspire/isotope/aa.rb
|
225
229
|
- lib/mspire/isotope/distribution.rb
|
@@ -292,6 +296,7 @@ files:
|
|
292
296
|
- spec/mspire/ident/pepxml/search_hit/modification_info_spec.rb
|
293
297
|
- spec/mspire/ident/pepxml_spec.rb
|
294
298
|
- spec/mspire/ident/protein_group_spec.rb
|
299
|
+
- spec/mspire/imzml/writer_spec.rb
|
295
300
|
- spec/mspire/isotope/aa_spec.rb
|
296
301
|
- spec/mspire/isotope/distribution_spec.rb
|
297
302
|
- spec/mspire/isotope_spec.rb
|
@@ -315,8 +320,11 @@ files:
|
|
315
320
|
- spec/mspire_spec.rb
|
316
321
|
- spec/obo_spec.rb
|
317
322
|
- spec/spec_helper.rb
|
323
|
+
- spec/testfiles/continuous_binary.tmp.ibd
|
318
324
|
- spec/testfiles/mspire/ident/peptide/db/uni_11_sp_tr.fasta
|
319
325
|
- spec/testfiles/mspire/ident/peptide/db/uni_11_sp_tr.msd_clvg2.min_aaseq4.yml
|
326
|
+
- spec/testfiles/mspire/imzml/continuous_binary_check.ibd
|
327
|
+
- spec/testfiles/mspire/imzml/processed_binary_check.ibd
|
320
328
|
- spec/testfiles/mspire/mzml/j24z.idx_comp.3.mzML
|
321
329
|
- spec/testfiles/mspire/mzml/mspire_simulated.MSn.check.mzML
|
322
330
|
- spec/testfiles/mspire/mzml/openms.noidx_nocomp.12.mzML
|
@@ -340,6 +348,7 @@ files:
|
|
340
348
|
- spec/testfiles/mspire/quant/remove_rest_of_proteins.rb
|
341
349
|
- spec/testfiles/mspire/quant/unlog_transform.rb
|
342
350
|
- spec/testfiles/plms1/output.key
|
351
|
+
- spec/testfiles/processed_binary.tmp.ibd
|
343
352
|
homepage: http://github.com/princelab/mspire
|
344
353
|
licenses:
|
345
354
|
- MIT
|