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 CHANGED
@@ -1 +1 @@
1
- 0.7.6
1
+ 0.7.7
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require 'mspire/imzml/writer/commandline'
5
+
6
+ argv = ARGV.dup
7
+ ARGV.clear
8
+ Mspire::Imzml::Writer::Commandline.run(argv)
9
+
@@ -7,29 +7,48 @@ module Mspire
7
7
  module CV
8
8
  module Paramable
9
9
 
10
- attr_accessor :params
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 = params.find {|v| v.accession == accession }
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
- params.find {|v| v.accession == accession }
47
+ accessionable_params.find {|v| v.accession == accession }
28
48
  end
29
49
 
30
-
31
50
  def param_exists_by_accession?(accession)
32
- params.any? {|v| v.accession == accession }
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
- @params ||= []
82
+ return self if args.first.nil?
62
83
  case (arg=args.first)
63
84
  when String
64
- @params << Mspire::CV::Param[ *args ]
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
- @params << param
99
+ @cv_params << param
77
100
  when Nokogiri::XML::NodeSet
78
101
  arg.each {|node| describe!(node) }
79
102
  else
80
- (@params << arg) if arg
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
- @params
109
+ self
83
110
  end
84
111
 
85
- # iterates over @params and calls .to_xml on each object.
86
- def to_xml(xml)
87
- if @params
88
- @params.each do |el|
89
- el.to_xml(xml)
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
- # the type of data array (:mz, :intensity, :mz_external, or :intensity_external)
22
- attr_accessor :type
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 type=:float64, compression=true
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
- @params.each {|param| param.to_xml(bda_n) } if @params
121
- unless @external
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
- if @type
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
- real_data_array = Mspire::Mzml::DataArray.new(data_ar)
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
@@ -17,7 +17,7 @@ module Mspire
17
17
  attr_accessor :software
18
18
 
19
19
  def initialize(id, components=[], opts={params: []})
20
- describe_many!(opts[:params])
20
+ super(opts)
21
21
  @id = id
22
22
  @components = components
23
23
  end
@@ -9,7 +9,7 @@ module Mspire
9
9
 
10
10
  def initialize(order, software, opts={params: []}, &block)
11
11
  @order, @software = order, software
12
- describe_many!(opts[:params])
12
+ super(opts)
13
13
  block.call(self) if block
14
14
  end
15
15
 
@@ -14,7 +14,7 @@ module Mspire
14
14
 
15
15
  def initialize(id, opts={params: []} )
16
16
  @id = id
17
- describe_many!(opts[:params])
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
- @params.each {|obj| obj.to_xml(fc_n) }
27
+ params.each {|obj| obj.to_xml(fc_n) }
28
28
  end
29
29
  builder
30
30
  end
@@ -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
- describe_many!(opts[:params])
33
+ super(opts)
34
34
  block.call(self) if block
35
35
  end
36
36
 
@@ -10,7 +10,7 @@ module Mspire
10
10
 
11
11
  def initialize(id, name, opts={params: []}, &block)
12
12
  @id, @name = id, name
13
- describe_many!(opts[:params])
13
+ super(opts)
14
14
  block.call(self) if block
15
15
  end
16
16
 
@@ -21,7 +21,7 @@ module Mspire
21
21
  attr_accessor :scan_windows
22
22
 
23
23
  def initialize(opts={params: []}, &block)
24
- describe_many!(opts[:params])
24
+ super(opts)
25
25
  block.call(self) if block
26
26
  end
27
27
 
@@ -13,13 +13,13 @@ module Mspire
13
13
  include Mspire::CV::Paramable
14
14
 
15
15
  def initialize(opts={params: []}, &block)
16
- describe_many!(opts[:params])
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
- @params.each {|param| param.to_xml(sl_n) } if @params
22
+ super(sl_n)
23
23
  self.each do |scan|
24
24
  scan.to_xml(sl_n)
25
25
  end
@@ -10,7 +10,7 @@ module Mspire
10
10
 
11
11
  def initialize(id, opts={params: []}, &block)
12
12
  @id = id
13
- describe_many!(opts[:params])
13
+ super(opts)
14
14
  block.call(self) if block
15
15
  end
16
16
 
@@ -11,7 +11,7 @@ module Mspire
11
11
 
12
12
  def initialize(id='mspire', version=Mspire::VERSION, opts={params: []}, &block)
13
13
  @id, @version = id, version
14
- describe_many!(opts[:params])
14
+ super(opts)
15
15
  block.call(self) if block
16
16
  end
17
17
 
@@ -33,7 +33,7 @@ module Mspire
33
33
 
34
34
  def initialize(id="sourcefile1", name="mspire-simulated", location='file://', opts={params: []}, &block)
35
35
  @id, @name, @location = id, name, location
36
- describe_many!(opts[:params])
36
+ super(opts)
37
37
  block.call(self) if block
38
38
  end
39
39
 
@@ -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
- describe_many! opts[:params]
148
+ params_initialize(opts)
148
149
  block.call(self) if block
149
150
  end
150
151
 
@@ -5,13 +5,14 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "mspire"
8
- s.version = "0.7.6"
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
@@ -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>
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.6
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