mspire 0.7.18 → 0.8.0

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.
Files changed (58) hide show
  1. data/VERSION +1 -1
  2. data/bin/mspire +5 -0
  3. data/lib/core_ext/enumerable.rb +8 -0
  4. data/lib/mspire/commandline.rb +39 -0
  5. data/lib/mspire/cv/paramable.rb +72 -35
  6. data/lib/mspire/imzml/writer/commandline.rb +16 -7
  7. data/lib/mspire/imzml/writer.rb +22 -14
  8. data/lib/mspire/mzml/activation.rb +0 -5
  9. data/lib/mspire/mzml/chromatogram.rb +41 -6
  10. data/lib/mspire/mzml/chromatogram_list.rb +2 -19
  11. data/lib/mspire/mzml/component.rb +28 -4
  12. data/lib/mspire/mzml/cv.rb +1 -0
  13. data/lib/mspire/mzml/data_array.rb +164 -154
  14. data/lib/mspire/mzml/data_array_container_like.rb +6 -13
  15. data/lib/mspire/mzml/data_processing.rb +19 -5
  16. data/lib/mspire/mzml/file_description.rb +22 -4
  17. data/lib/mspire/mzml/index.rb +53 -0
  18. data/lib/mspire/mzml/index_list.rb +64 -55
  19. data/lib/mspire/mzml/instrument_configuration.rb +22 -7
  20. data/lib/mspire/mzml/io_index.rb +79 -0
  21. data/lib/mspire/mzml/io_indexable_list.rb +71 -0
  22. data/lib/mspire/mzml/isolation_window.rb +0 -5
  23. data/lib/mspire/mzml/parser.rb +10 -0
  24. data/lib/mspire/mzml/plms1.rb +14 -24
  25. data/lib/mspire/mzml/precursor.rb +41 -19
  26. data/lib/mspire/mzml/processing_method.rb +34 -7
  27. data/lib/mspire/mzml/product.rb +14 -1
  28. data/lib/mspire/mzml/reader.rb +154 -0
  29. data/lib/mspire/mzml/referenceable_param_group.rb +9 -2
  30. data/lib/mspire/mzml/run.rb +62 -5
  31. data/lib/mspire/mzml/sample.rb +16 -6
  32. data/lib/mspire/mzml/scan.rb +31 -16
  33. data/lib/mspire/mzml/scan_list.rb +18 -5
  34. data/lib/mspire/mzml/scan_settings.rb +4 -5
  35. data/lib/mspire/mzml/scan_window.rb +0 -6
  36. data/lib/mspire/mzml/selected_ion.rb +1 -8
  37. data/lib/mspire/mzml/software.rb +9 -4
  38. data/lib/mspire/mzml/source_file.rb +8 -4
  39. data/lib/mspire/mzml/spectrum.rb +60 -35
  40. data/lib/mspire/mzml/spectrum_list.rb +5 -34
  41. data/lib/mspire/mzml.rb +72 -210
  42. data/lib/mspire/plms1.rb +3 -0
  43. data/spec/mspire/cv/paramable_spec.rb +3 -3
  44. data/spec/mspire/mzml/data_array_spec.rb +19 -6
  45. data/spec/mspire/mzml/file_content_spec.rb +1 -4
  46. data/spec/mspire/mzml/index_list_spec.rb +5 -12
  47. data/spec/mspire/mzml/plms1_spec.rb +5 -9
  48. data/spec/mspire/mzml/referenceable_param_group_spec.rb +3 -3
  49. data/spec/mspire/mzml/source_file_spec.rb +1 -2
  50. data/spec/mspire/mzml/spectrum_list_spec.rb +54 -0
  51. data/spec/mspire/mzml/spectrum_spec.rb +2 -4
  52. data/spec/mspire/mzml_spec.rb +241 -21
  53. data/spec/spec_helper.rb +1 -0
  54. data/spec/testfiles/mspire/mzml/1_BB7_SIM_478.5.mzML +103 -0
  55. data/spec/testfiles/mspire/mzml/j24z.idx_comp.3.mzML +6 -6
  56. metadata +14 -6
  57. data/bin/mzml_to_imzml +0 -9
  58. data/spec/mspire/mzml/file_description_spec.rb +0 -12
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.18
1
+ 0.8.0
data/bin/mspire ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mspire/commandline'
4
+
5
+ Mspire::Commandline.run(ARGV)
@@ -0,0 +1,8 @@
1
+
2
+ module Enumerable
3
+ # File activesupport/lib/active_support/core_ext/enumerable.rb, line 94
4
+ def index_by
5
+ return to_enum :index_by unless block_given?
6
+ Hash[map { |elem| [yield(elem), elem] }]
7
+ end
8
+ end
@@ -0,0 +1,39 @@
1
+ require 'trollop'
2
+ require 'mspire/imzml/writer/commandline'
3
+
4
+ module Mspire
5
+ module Commandline
6
+ SUB_COMMANDS = {
7
+ to_imzml: 'convert mzml to imzml',
8
+ }
9
+
10
+ def self.run(argv)
11
+
12
+ parser = Trollop::Parser.new do
13
+ banner "usage: mspire <subcommand> [OPTIONS]"
14
+ text ""
15
+ text "subcommands: "
16
+ SUB_COMMANDS.each do |k,v|
17
+ text " #{k} #{v}"
18
+ end
19
+ text ""
20
+ stop_on SUB_COMMANDS.keys.map(&:to_s)
21
+ end
22
+
23
+ begin
24
+ global_opts = parser.parse(argv)
25
+ rescue Trollop::HelpNeeded
26
+ parser.educate && exit
27
+ end
28
+
29
+ parser.educate && exit unless argv.size > 0
30
+
31
+ cmd = argv.shift
32
+ cmd_parser =
33
+ case cmd.to_sym
34
+ when :to_imzml
35
+ Mspire::Imzml::Writer::Commandline.run(argv, global_opts)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -16,6 +16,14 @@ module Mspire
16
16
  cv_params + ref_param_groups.flat_map(&:params) + user_params
17
17
  end
18
18
 
19
+ def each_param(&block)
20
+ return enum_for __method__ unless block
21
+ cv_params.each(&block)
22
+ ref_param_groups.flat_map(&:params).each(&block)
23
+ user_params.each(&block)
24
+ nil
25
+ end
26
+
19
27
  def params?
20
28
  total_num_params = cv_params.size +
21
29
  ref_param_groups.reduce(0) {|sum,group| sum +
@@ -23,6 +31,13 @@ module Mspire
23
31
  total_num_params > 0
24
32
  end
25
33
 
34
+ def each_accessionable_param(&block)
35
+ return enum_for __method__ unless block
36
+ cv_params.each(&block)
37
+ ref_param_groups.flat_map(&:params).each(&block)
38
+ nil
39
+ end
40
+
26
41
  def accessionable_params
27
42
  cv_params + ref_param_groups.flat_map(&:params)
28
43
  end
@@ -38,7 +53,7 @@ module Mspire
38
53
  # returns the value if the param exists by that name. Returns true if
39
54
  # the param exists but has no value. returns false if no param
40
55
  def fetch(name)
41
- param = params.find {|param| param.name == name}
56
+ param = each_param.find {|param| param.name == name}
42
57
  if param
43
58
  param.value || true
44
59
  else
@@ -60,19 +75,20 @@ module Mspire
60
75
  params.any? {|param| param.name == name }
61
76
  end
62
77
 
63
- def initialize(opts={params: []})
78
+ def initialize
64
79
  @cv_params = []
65
80
  @user_params = []
66
81
  @ref_param_groups = []
67
- describe_many!(opts[:params])
68
82
  end
83
+ alias_method :params_init, :initialize
69
84
 
70
85
  def param_by_accession(acc)
71
- accessionable_params.find {|v| v.accession == acc }
86
+ each_accessionable_param.find {|v| v.accession == acc }
72
87
  end
73
88
  alias_method :param_by_acc, :param_by_accession
74
89
 
75
90
  # takes an array of values, each of which is fed into describe!
91
+ # returns self.
76
92
  def describe_many!(array)
77
93
  array.each do |arg|
78
94
  if arg.is_a?(Array)
@@ -81,10 +97,51 @@ module Mspire
81
97
  describe!(arg)
82
98
  end
83
99
  end
100
+ self
101
+ end
102
+
103
+ # reads the paramable nodes and returns self. Use this if your element
104
+ # does not have anything besides paramable elements.
105
+ def describe_self_from_xml!(xml_node, ref_hash=nil)
106
+ describe_from_xml!(xml_node, ref_hash)
107
+ self
108
+ end
109
+
110
+ # takes a node with children that are cvParam, userParam or
111
+ # referenceableParamGroupRef and a hash containing
112
+ # referenceableParamGroup objects indexed by id. The only time ref_hash
113
+ # should be left nil is for the referenceableParamGroup itself.
114
+ #
115
+ # All param elements are required to appear before other elements, so
116
+ # the code walks through each child node to see if it is a paramable
117
+ # element. The first child node that is not paramable is returned (or
118
+ # nil if none)
119
+ #
120
+ # returns the next child node after the paramable elements or nil if none
121
+ def describe_from_xml!(xml_node, ref_hash=nil)
122
+ return nil unless (child_n = xml_node.child)
123
+ loop do
124
+ array =
125
+ case child_n.name
126
+ when 'referenceableParamGroupRef'
127
+ @ref_param_groups << ref_hash[child_n[:ref]]
128
+ when 'cvParam'
129
+ @cv_params << Mspire::CV::Param[ child_n[:accession], child_n[:value] ]
130
+ when 'userParam'
131
+ @user_params << Mspire::UserParam.new(child_n[:name], child_n[:value], child_n[:type])
132
+ else # assumes that the above precede any following children as per the spec
133
+ break
134
+ end
135
+ if (unit_acc = child_n[:unitAccession])
136
+ array.last.unit = ::CV::Param.new(child_n[:unitCvRef], unit_acc, child_n[:unitName])
137
+ end
138
+ break unless child_n = child_n.next
139
+ end
140
+ child_n
84
141
  end
85
142
 
86
- # Expects arguments describing a single CV::Param or Mapire::UserParam.
87
- # Will also accept an Nokogiri::XML::Node or Nokogiri::XML::NodeSet
143
+ # Expects arguments describing a single CV::Param, Mspire::UserParam, or
144
+ # Mspire::Mzml::ReferenceableParamGroup
88
145
  #
89
146
  # obj.describe! 'MS:1000130' # a positive scan
90
147
  # obj.describe! CV::Param['MS:1000130'] # same behavior
@@ -92,12 +149,6 @@ module Mspire
92
149
  # # base peak intensity, units=number of counts
93
150
  # obj.describe! "MS:1000505", 1524.5865478515625, 'MS:1000131'
94
151
  #
95
- # # given an XML::NodeSet
96
- # obj.describe! xml_node.xpath('.//cvParam')
97
- #
98
- # # given an XML
99
- # obj.describe! xml_node.xpath('.//cvParam').first
100
- #
101
152
  # returns self
102
153
  def describe!(*args)
103
154
  return self if args.first.nil?
@@ -106,40 +157,26 @@ module Mspire
106
157
  @cv_params << Mspire::CV::Param[ *args ]
107
158
  when Mspire::Mzml::ReferenceableParamGroup
108
159
  @ref_param_groups << arg
109
- when Nokogiri::XML::Node # a nokogiri node in particular
110
- param =
111
- case arg.name
112
- when 'cvParam'
113
- Mspire::CV::Param[ arg[:accession], arg[:value] ]
114
- when 'userParam'
115
- Mspire::UserParam.new(arg[:name], arg[:value], arg[:type])
116
- end
117
- if (unit_acc = arg[:unitAccession])
118
- param.unit = ::CV::Param.new(arg[:unitCvRef], unit_acc, arg[:unitName])
119
- end
120
- @cv_params << param
121
- when Nokogiri::XML::NodeSet
122
- arg.each {|node| describe!(node) }
123
160
  else
124
161
  if arg.is_a?(Mspire::UserParam)
125
162
  @user_params << arg
126
163
  else
127
- (@cv_params << arg) if arg
164
+ @cv_params << arg
128
165
  end
129
166
  end
130
167
  self
131
168
  end
132
169
 
133
- # iterates over @params and calls .to_xml on each object.
134
- def to_xml(xml)
135
- [:ref_param_groups, :cv_params, :user_params].each do |kind|
136
- self.send(kind).each do |obj|
137
- obj.to_xml(xml)
138
- end
170
+ # iterates over @params and calls .to_xml on each object.
171
+ def to_xml(xml)
172
+ [:ref_param_groups, :cv_params, :user_params].each do |kind|
173
+ self.send(kind).each do |obj|
174
+ obj.to_xml(xml)
139
175
  end
140
- xml
141
176
  end
142
-
177
+ xml
143
178
  end
179
+
144
180
  end
145
181
  end
182
+ end
@@ -13,7 +13,9 @@ end
13
13
 
14
14
  module Mspire::Imzml::Writer::Commandline
15
15
 
16
- def self.run(argv, progname=$0)
16
+ # generates the Trollop parser
17
+ def self.parser
18
+ return @parser if @parser
17
19
 
18
20
  default_config = "config.yaml"
19
21
  scan_patterns = %w(flyback meandering random)
@@ -24,9 +26,9 @@ module Mspire::Imzml::Writer::Commandline
24
26
  default_pixel_size = '1x1'
25
27
  matrix_application_types = %w(sprayed precoated printed drieddroplet)
26
28
 
27
- parser = Trollop::Parser.new do
29
+ @parser = Trollop::Parser.new do
28
30
  banner <<-EOS
29
- usage: #{File.basename(progname)} [OPTIONS] <file>.mzML ..."
31
+ usage: mspire to_imzml [OPTIONS] <file>.mzML ..."
30
32
  output: <file>.imzML and <file>.ibd
31
33
 
32
34
  * imzML docs:
@@ -43,6 +45,9 @@ output: <file>.imzML and <file>.ibd
43
45
  opt :combine, "combine all files and set the base name of resulting imzML and ibd files", :type => String
44
46
  opt :outfile, "use a specific basename for the resulting file. Acts like --combine for multiple files", :type => String
45
47
 
48
+ text "\nediting:"
49
+ opt :trim_files, "determines the least number of spectra in a file and shortens all spectra to be the same length"
50
+
46
51
  text "\nimaging:"
47
52
  opt :continuous, "assumes m/z values are the same for every scan. The 'processed' storage format is used unless this flag is given."
48
53
  opt :scan_pattern, scan_patterns.join('|'), :default => scan_patterns.first
@@ -76,8 +81,15 @@ output: <file>.imzML and <file>.ibd
76
81
  # filters (cutoff / max # peaks, etc.)
77
82
  # ms_level, etc.
78
83
  end
84
+ end
85
+
86
+ def self.run(argv, globalopts)
87
+ begin
88
+ opts = parser.parse(argv)
89
+ rescue Trollop::HelpNeeded
90
+ return parser.educate
91
+ end
79
92
 
80
- opts = parser.parse(argv)
81
93
  opts = Hash[YAML.load_file(opts[:config]).map {|k,v| [k.to_sym, v]}].merge(opts) if opts[:config]
82
94
 
83
95
  opts[:combine] ||= opts.delete(:outfile)
@@ -104,6 +116,3 @@ output: <file>.imzML and <file>.ibd
104
116
 
105
117
  end
106
118
  end
107
-
108
-
109
-
@@ -215,13 +215,13 @@ module Mspire::Imzml
215
215
  def create_file_description(source_files, config)
216
216
  Mspire::Mzml::FileDescription.new do |fd|
217
217
 
218
- fd.file_content = Mspire::Mzml::FileContent.new :params => [
218
+ fd.file_content = Mspire::Mzml::FileContent.new.describe_many!( [
219
219
  'MS:1000579', # MS1 Spectrum
220
220
  config[:profile] ? 'MS:1000128' : 'MS:1000127',
221
221
  ['IMS:1000080', "{"+config[:uuid_hyphenated]+"}"],
222
222
  ['IMS:1000091', config[:ibd_sha1]],
223
223
  (config[:data_structure] == :processed) ? 'IMS:1000031' : 'IMS:1000030',
224
- ]
224
+ ] )
225
225
 
226
226
  fd.source_files.replace(source_files)
227
227
  if [:name, :organization, :address, :email].any? {|key| config[key] }
@@ -267,9 +267,9 @@ module Mspire::Imzml
267
267
  "MS:1000127", # centroid spectrum
268
268
  "MS:1000130" # <- positive scan
269
269
  ]}.map do |id, list|
270
- Mspire::Mzml::ReferenceableParamGroup.new id, params: list
270
+ Mspire::Mzml::ReferenceableParamGroup.new(id).describe_many!(list)
271
271
  end
272
- Hash[ rparms.map {|parm| [parm.id, parm]} ]
272
+ Hash[ rparms.map {|prm_group_obj| [prm_group_obj.id, prm_group_obj]} ]
273
273
  end
274
274
 
275
275
  # mzml_filenames can each be a partial or relative path
@@ -286,6 +286,9 @@ module Mspire::Imzml
286
286
  # :solvent_flowrate => flowrate of the solvent (ml/min)
287
287
  # :spray_voltage => spray voltage in kV
288
288
  # :target_material => the material the target is made of
289
+ # editing:
290
+ # :trim_files => determines min # spectra in file and lops
291
+ # off the ends of other files.
289
292
  # general:
290
293
  # :omit_zeros => remove zero values
291
294
  # :combine => use this outfile base name to combine files
@@ -311,6 +314,10 @@ module Mspire::Imzml
311
314
  config[:uuid_hyphenated] = uuid_with_hyphens
312
315
  config[:uuid] = uuid_with_hyphens.gsub('-','')
313
316
 
317
+ if config[:trim_files]
318
+ config[:trim_to] = mzml_filenames.map {|fn| Mspire::Mzml.open(fn, &:size) }.min
319
+ end
320
+
314
321
  sourcefile_id_parallel_to_spectra = []
315
322
  sourcefile_ids = []
316
323
  all_spectra_iter = Enumerator.new do |yielder|
@@ -318,7 +325,8 @@ module Mspire::Imzml
318
325
  sourcefile_id = "source_file_#{i}"
319
326
  sourcefile_ids << sourcefile_id
320
327
  Mspire::Mzml.open(mzml_filename) do |mzml|
321
- mzml.each do |spec|
328
+ mzml.each_with_index do |spec,i|
329
+ break if config[:trim_to] && (i >= config[:trim_to])
322
330
  sourcefile_id_parallel_to_spectra << sourcefile_id
323
331
  yielder << spec
324
332
  end
@@ -359,12 +367,12 @@ module Mspire::Imzml
359
367
 
360
368
  imzml.referenceable_param_groups = rparms_by_id.values
361
369
  # skip sample list for now
362
- mspire_software = Mspire::Mzml::Software.new( "mspire", Mspire::VERSION, params: ["MS:1000799"] )
370
+ mspire_software = Mspire::Mzml::Software.new("mspire", Mspire::VERSION).describe!("MS:1000799")
363
371
  imzml.software_list << mspire_software
364
372
 
365
373
  scan_setting_params = image_hash_to_cvs( config )
366
374
  scan_setting_params.push *experiment_hash_to_cvs( config )
367
- imzml.scan_settings_list = [Mspire::Mzml::ScanSettings.new("scansettings1", params: scan_setting_params)]
375
+ imzml.scan_settings_list = [Mspire::Mzml::ScanSettings.new("scansettings1").describe_many!(scan_setting_params)]
368
376
 
369
377
  warn 'todo: need to borrow instrumentConfiguration from original mzml'
370
378
 
@@ -376,20 +384,20 @@ module Mspire::Imzml
376
384
  # this is a generic 'file format conversion' but its the closest we
377
385
  # have for mzml to imzml (which is really mzml to mzml)
378
386
  data_processing_obj = Mspire::Mzml::DataProcessing.new('mzml_to_imzml')
379
- data_processing_obj.processing_methods << Mspire::Mzml::ProcessingMethod.new(1, mspire_software, params: ['MS:1000530'] )
387
+ data_processing_obj.processing_methods << Mspire::Mzml::ProcessingMethod.new(mspire_software).describe!('MS:1000530')
380
388
  imzml.data_processing_list << data_processing_obj
381
389
 
382
390
  warn "not implemented 'omit_zeros' yet"
383
391
  # low intensity data point removal: "MS:1000594"
384
392
  imzml.run = Mspire::Mzml::Run.new("run1", default_instrument_config) do |run|
385
- spec_list = Mspire::Mzml::SpectrumList.new(data_processing_obj)
393
+ spectra = []
386
394
  data_info_pairs.zip(xy_positions_array, sourcefile_id_parallel_to_spectra).each_with_index do |(pair, xy, sourcefile_id),i|
387
395
  # TODO: we should probably copy the id from the orig mzml (e.g.
388
396
  # scan=1)
389
- spectrum = Mspire::Mzml::Spectrum.new("spectrum#{i}", params: [rparms_by_id[:spectrum1]])
397
+ spectrum = Mspire::Mzml::Spectrum.new("spectrum#{i}").describe!(rparms_by_id[:spectrum1])
390
398
  spectrum.source_file = sourcefile_id_to_sourcefile[sourcefile_id]
391
- scan_list = Mspire::Mzml::ScanList.new(params: ['MS:1000795']) # no combination
392
- scan = Mspire::Mzml::Scan.new( params: [rparms_by_id[:scan1], ["IMS:1000050", xy[0]], ["IMS:1000051", xy[1]]] )
399
+ scan_list = Mspire::Mzml::ScanList.new.describe!('MS:1000795') # no combination
400
+ scan = Mspire::Mzml::Scan.new.describe_many!([rparms_by_id[:scan1], ["IMS:1000050", xy[0]], ["IMS:1000051", xy[1]]])
393
401
  scan.instrument_configuration = default_instrument_config
394
402
  spectrum.scan_list = (scan_list << scan)
395
403
 
@@ -402,9 +410,9 @@ module Mspire::Imzml
402
410
  data_array
403
411
  end
404
412
  spectrum.data_arrays = data_arrays
405
- spec_list << spectrum
413
+ spectra << spectrum
406
414
  end
407
- run.spectrum_list = spec_list
415
+ run.spectrum_list = Mspire::Mzml::SpectrumList.new(data_processing_obj, spectra)
408
416
  end # run
409
417
  end # imzml
410
418
  imzml_obj.to_xml(config[:imzml_filename])
@@ -28,11 +28,6 @@ module Mspire
28
28
  # et al.
29
29
  class Activation
30
30
  include Mspire::CV::Paramable
31
- def self.from_xml(xml)
32
- obj = self.new
33
- [:cvParam, :userParam].each {|v| obj.describe! xml.xpath("./#{v}") }
34
- obj
35
- end
36
31
  end
37
32
  end
38
33
  end
@@ -4,6 +4,7 @@ module Mspire
4
4
  class Mzml
5
5
  class Chromatogram
6
6
  include Mspire::Mzml::DataArrayContainerLike
7
+ alias_method :params_initialize, :initialize
7
8
 
8
9
  # (optional) precursor isolations to the chromatogram currently being
9
10
  # described
@@ -12,16 +13,50 @@ module Mspire
12
13
  # (optional) Description of product isolation to the chromatogram
13
14
  attr_accessor :product
14
15
 
15
- def initialize(*args, &block)
16
- super(*args)
17
- block.call(self) if block
16
+ def initialize(id)
17
+ @id = id
18
+ params_initialize
19
+ yield(self) if block_given?
20
+ end
21
+
22
+ def self.from_xml(xml, link)
23
+ obj = self.new(xml[:id])
24
+
25
+ obj.data_processing = link[:data_processing_hash][xml[:dataProcessingRef]] || link[:spectrum_default_data_processing]
26
+
27
+ xml_n = obj.describe_from_xml!(xml, link[:ref_hash])
28
+
29
+ loop do
30
+ case xml_n.name
31
+ when 'precursor'
32
+ obj.precursor = Mspire::Mzml::Precursor.from_xml(xml_n, link)
33
+ when 'product'
34
+ obj.product = Mspire::Mzml::Product.from_xml(xml_n, link)
35
+ when 'binaryDataArrayList'
36
+ obj.data_arrays = Mspire::Mzml::DataArray.data_arrays_from_xml(xml_n, link)
37
+ break
38
+ end
39
+ break unless xml_n = xml_n.next
40
+ end
41
+ obj
42
+ end
43
+
44
+ def times
45
+ data_arrays[0]
46
+ end
47
+
48
+ def intensities
49
+ data_arrays[1]
18
50
  end
19
51
 
20
52
  # see SpectrumList for generating the entire list
21
53
  def to_xml(builder, opts={})
22
- super(builder) do |node|
23
- @precursor.to_xml(node) if @precursor
24
- @product.to_xml(node) if @product
54
+ atts = data_array_xml_atts(default_ids)
55
+ builder.chromatogram(atts) do |chrom_n|
56
+ super(chrom_n)
57
+ @precursor.to_xml(chrom_n) if @precursor
58
+ @product.to_xml(chrom_n) if @product
59
+ Mspire::Mzml::DataArray.list_xml(@data_arrays, chrom_n) if @data_arrays
25
60
  end
26
61
  end
27
62
  end
@@ -1,26 +1,9 @@
1
1
 
2
+ require 'mspire/mzml/io_indexable_list'
2
3
 
3
4
  module Mspire
4
5
  class Mzml
5
- class ChromatogramList < Array
6
-
7
- # a DataProcessing object
8
- attr_reader :default_data_processing
9
-
10
- def initialize(default_data_processing, chromatograms=[])
11
- @default_data_processing = default_data_processing
12
- super(chromatograms)
13
- end
14
-
15
- def to_xml(builder)
16
- builder.chromatogramList(count: self.size, defaultDataProcessingRef: @default_data_processing.id) do |chrl_n|
17
- self.each do |chromatogram|
18
- chromatogram.to_xml(chrl_n)
19
- end
20
- end
21
- builder
22
- end
23
-
6
+ class ChromatogramList < IOIndexableList
24
7
  end
25
8
  end
26
9
  end
@@ -3,19 +3,43 @@ require 'mspire/mzml/list'
3
3
 
4
4
  module Mspire
5
5
  class Mzml
6
+ # order is not an intrinsic property of this object, so it
6
7
  module Component
7
8
  include Mspire::CV::Paramable
9
+ # using custom list_xml, so no extend Mspire::Mzml::List
8
10
 
9
- attr_accessor :order
11
+ def initialize
12
+ params_init
13
+ yield(self) if block_given?
14
+ end
10
15
 
11
- def to_xml(builder)
12
- builder.component(order: @order) do |c_n|
16
+ def to_xml(builder, order)
17
+ builder.component(order: order) do |c_n|
13
18
  super(c_n)
14
19
  end
15
20
  builder
16
21
  end
17
22
 
18
- extend(Mspire::Mzml::List)
23
+ def self.list_xml(components, builder)
24
+ builder.componentList(count: components.size) do |xml_n|
25
+ components.each_with_index do |component, order|
26
+ component.to_xml(xml_n, order)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ class Source
33
+ include Component
19
34
  end
35
+
36
+ class Analyzer
37
+ include Component
38
+ end
39
+
40
+ class Detector
41
+ include Component
42
+ end
43
+
20
44
  end
21
45
  end
@@ -2,6 +2,7 @@
2
2
  module Mspire
3
3
  class Mzml
4
4
  class CV
5
+ # note: CV is NOT paramable!
5
6
 
6
7
  # (required) The short label to be used as a reference tag with which to refer to
7
8
  # this particular Controlled Vocabulary source description (e.g., from