mspire 0.7.6 → 0.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|