mspire-lipid 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,183 @@
1
+ #<OpenBabel::OBMol:0x00000000b71c90>
2
+ ---
3
+ - add
4
+ - reserve_atoms
5
+ - create_atom
6
+ - create_bond
7
+ - create_residue
8
+ - destroy_atom
9
+ - destroy_bond
10
+ - destroy_residue
11
+ - add_atom
12
+ - insert_atom
13
+ - add_bond
14
+ - add_residue
15
+ - new_atom
16
+ - new_bond
17
+ - new_residue
18
+ - delete_atom
19
+ - delete_bond
20
+ - delete_residue
21
+ - begin_modify
22
+ - end_modify
23
+ - get_mod
24
+ - increment_mod
25
+ - decrement_mod
26
+ - get_flags
27
+ - get_title
28
+ - num_atoms
29
+ - num_bonds
30
+ - num_hvy_atoms
31
+ - num_residues
32
+ - num_rotors
33
+ - get_atom
34
+ - get_atom_by_id
35
+ - get_first_atom
36
+ - get_bond_by_id
37
+ - get_bond
38
+ - get_residue
39
+ - get_internal_coord
40
+ - get_torsion
41
+ - get_angle
42
+ - get_formula
43
+ - get_spaced_formula
44
+ - get_mol_wt
45
+ - get_exact_mass
46
+ - get_total_charge
47
+ - get_total_spin_multiplicity
48
+ - get_dimension
49
+ - get_coordinates
50
+ - get_sssr
51
+ - get_lssr
52
+ - automatic_formal_charge
53
+ - automatic_partial_charge
54
+ - set_title
55
+ - set_formula
56
+ - set_energy
57
+ - set_dimension
58
+ - set_total_charge
59
+ - set_total_spin_multiplicity
60
+ - set_internal_coord
61
+ - set_automatic_formal_charge
62
+ - set_automatic_partial_charge
63
+ - set_aromatic_perceived
64
+ - set_sssrperceived
65
+ - set_lssrperceived
66
+ - set_ring_atoms_and_bonds_perceived
67
+ - set_atom_types_perceived
68
+ - set_ring_types_perceived
69
+ - set_chains_perceived
70
+ - set_chirality_perceived
71
+ - set_partial_charges_perceived
72
+ - set_hybridization_perceived
73
+ - set_implicit_valence_perceived
74
+ - set_kekule_perceived
75
+ - set_closure_bonds_perceived
76
+ - set_hydrogens_added
77
+ - set_corrected_for_ph
78
+ - set_aromatic_corrected
79
+ - set_spin_multiplicity_assigned
80
+ - set_flags
81
+ - unset_aromatic_perceived
82
+ - unset_sssrperceived
83
+ - unset_ring_types_perceived
84
+ - unset_partial_charges_perceived
85
+ - unset_implicit_valence_perceived
86
+ - unset_hydrogens_added
87
+ - unset_flag
88
+ - renumber_atoms
89
+ - set_coordinates
90
+ - to_inertial_frame
91
+ - translate
92
+ - rotate
93
+ - kekulize
94
+ - perceive_kekule_bonds
95
+ - new_perceive_kekule_bonds
96
+ - delete_hydrogens
97
+ - delete_non_polar_hydrogens
98
+ - delete_hydrogen
99
+ - add_hydrogens
100
+ - add_polar_hydrogens
101
+ - strip_salts
102
+ - separate
103
+ - get_next_fragment
104
+ - convert_dative_bonds
105
+ - correct_for_ph
106
+ - assign_spin_multiplicity
107
+ - set_is_pattern_structure
108
+ - center
109
+ - set_torsion
110
+ - find_sssr
111
+ - find_lssr
112
+ - find_ring_atoms_and_bonds
113
+ - find_chiral_centers
114
+ - find_children
115
+ - find_largest_fragment
116
+ - contig_frag_list
117
+ - align
118
+ - connect_the_dots
119
+ - perceive_bond_orders
120
+ - find_angles
121
+ - find_torsions
122
+ - get_gtdvector
123
+ - get_givector
124
+ - get_gidvector
125
+ - has_2d
126
+ - has_3d
127
+ - has_non_zero_coords
128
+ - has_aromatic_perceived
129
+ - has_sssrperceived
130
+ - has_lssrperceived
131
+ - has_ring_atoms_and_bonds_perceived
132
+ - has_atom_types_perceived
133
+ - has_ring_types_perceived
134
+ - has_chirality_perceived
135
+ - has_partial_charges_perceived
136
+ - has_hybridization_perceived
137
+ - has_implicit_valence_perceived
138
+ - has_kekule_perceived
139
+ - has_closure_bonds_perceived
140
+ - has_chains_perceived
141
+ - has_hydrogens_added
142
+ - has_aromatic_corrected
143
+ - is_corrected_for_ph
144
+ - has_spin_multiplicity_assigned
145
+ - is_chiral
146
+ - empty
147
+ - num_conformers
148
+ - set_conformers
149
+ - add_conformer
150
+ - set_conformer
151
+ - copy_conformer
152
+ - delete_conformer
153
+ - get_conformer
154
+ - set_energies
155
+ - get_energies
156
+ - get_energy
157
+ - begin_conformer
158
+ - next_conformer
159
+ - get_conformers
160
+ - begin_atoms
161
+ - end_atoms
162
+ - begin_bonds
163
+ - end_bonds
164
+ - begin_residues
165
+ - end_residues
166
+ - begin_atom
167
+ - next_atom
168
+ - begin_bond
169
+ - next_bond
170
+ - begin_residue
171
+ - next_residue
172
+ - begin_internal_coord
173
+ - next_internal_coord
174
+ - clear
175
+ - do_transformations
176
+ - has_data
177
+ - delete_data
178
+ - clone_data
179
+ - data_size
180
+ - get_all_data
181
+ - get_data
182
+ - begin_data
183
+ - end_data
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+ require 'openbabel'
5
+ include OpenBabel
6
+
7
+ if ARGV.size == 0
8
+ puts "smiles and smart"
9
+ exit
10
+ end
11
+
12
+ (smiles_string, smart_search) = ARGV
13
+
14
+ smi_to_svg = OBConversion.new
15
+ smi_to_svg.set_in_and_out_formats("smi", "svg")
16
+
17
+ obmol = OBMol.new
18
+
19
+ smi_to_svg.read_string(obmol, smiles_string)
20
+ obmol.add_hydrogens
21
+
22
+ p obmol.get_formula
23
+ svg_string = smi_to_svg.write_string(obmol).rstrip
24
+ File.write("before.svg", svg_string)
25
+
26
+ bond_triplets = []
27
+ (1..obmol.num_bonds).each do |i|
28
+ bond = obmol.get_bond(i)
29
+ if bond
30
+ bond_triplets << [bond.get_begin_atom, bond.get_end_atom, bond]
31
+ end
32
+ end
33
+
34
+ (1..obmol.num_atoms).each do |i|
35
+ atom = obmol.get_atom(i)
36
+ if atom.matches_smarts("C(=O)CC")
37
+ bond_triplet = bond_triplets.find {|triplet| triplet.include?(atom) }
38
+ obmol.delete_bond(bond_triplet.last)
39
+ atom.begin_nbr_atom
40
+ atom.next_nbr_atom
41
+ break
42
+ end
43
+ end
44
+
45
+ molecules = obmol.separate
46
+ molecules.each_with_index do |mol,i|
47
+ puts "mol #{i}"
48
+ p mol.get_formula
49
+ p mol.add_hydrogens
50
+ p mol.get_formula
51
+ svg_string = smi_to_svg.write_string(mol).rstrip
52
+ File.write("after_#{i}.svg", svg_string)
53
+ end
54
+
55
+
56
+
57
+ #puts (obmol.methods - Object.new.methods).map(&:to_s).to_yaml
58
+ #p obmol.exact_mass
59
+
60
+
61
+
62
+
63
+ =begin
64
+ $obConversion->ReadFile($obMol, $filename);
65
+
66
+ for (1..$obMol->NumAtoms()) {
67
+ $atom = $obMol->GetAtom($_);
68
+ # look to see if this atom is a thiophene sulfur atom
69
+ if ($atom->MatchesSMARTS("[#16D2]([#6D3H1])[#6D3H1]")) {
70
+ $sulfurIdx = $atom->GetIdx();
71
+ # see if this atom is one of the carbon atoms bonded to a thiophene sulfur
72
+ } elsif ($atom->MatchesSMARTS("[#6D3H1]([#16D2][#6D3H1])[#6]") ) {
73
+ if ($c2Idx == 0) { $c2Idx = $atom->GetIdx(); }
74
+ else {$c5Idx = $atom->GetIdx(); }
75
+ }
76
+ }
77
+
78
+ # Get the actual atom objects -- indexing will change as atoms are added and deleted!
79
+ $sulfurAtom = $obMol->GetAtom($sulfurIdx);
80
+ $c2Atom = $obMol->GetAtom($c2Idx);
81
+ $c5Atom = $obMol->GetAtom($c5Idx);
82
+
83
+ $obMol->DeleteAtom($sulfurAtom);
84
+
85
+ $obMol->DeleteHydrogens($c2Atom);
86
+ $obMol->DeleteHydrogens($c5Atom);
87
+
88
+ $c2Atom->SetAtomicNum(1);
89
+ $c5Atom->SetAtomicNum(1);
90
+
91
+ $obConversion->WriteFile($obMol, "$filename.mol");
92
+
93
+ =end
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'trollop'
4
+
5
+ require 'bsearch'
6
+
7
+ require 'mspire/lipid/ion'
8
+ require 'mspire/lipid/modification'
9
+ require 'mspire/lipid_maps'
10
+
11
+ parser = Trollop::Parser.new do
12
+ banner "usage: #{File.basename(__FILE__)} <lipidmaps.tsv> <m/z> ..."
13
+ banner ""
14
+ opt :top_n, "how many closest ions to print", :default => 3
15
+ banner ""
16
+ text "modifications: (at least 1 charged mod is required)"
17
+ text "will search for i down to 1 mod: "
18
+ #opt :newmod, "<name>:<formula>:<charge>:<L/G>:<#occurences> L/G=loss or gain", :type => :string, :multi => true
19
+ opt :lithium, "Li+ gain", :default => 0
20
+ opt :sodium, "Na+ gain", :default => 0
21
+ opt :ammonium, "", :default => 0
22
+ opt :ammonia_loss, "search for i down to 1 ammonia losses", :default => 0
23
+ opt :carbon_dioxide_loss, "search for i down to 1 CO2 losses", :default => 0
24
+ opt :proton_gain, "search for i down to 1 proton additions", :default => 0
25
+ opt :proton_loss, "search for i down to 1 proton losses", :default => 0
26
+ opt :water_loss, "if used, *all* mods are also considered with i down to 0 water losses", :default => 0
27
+ opt :acetate, "search for i down to 0 water losses", :default => 0
28
+ text ""
29
+ text "other:"
30
+ opt :textfile, "a text file with m/z values, one per line", :type => String
31
+ opt :lower_bound, "use lower bound searching (requires m/z's to be in sorted order)"
32
+ opt :sort, "sorts the m/z's"
33
+ end
34
+
35
+ opts = parser.parse(ARGV)
36
+
37
+ if ARGV.size == 0
38
+ parser.educate
39
+ exit
40
+ end
41
+
42
+ CHARGED_MODS = [:lithium, :sodium, :ammonium, :proton_gain, :proton_loss]
43
+ UNCHARGED_MODS = [:water_loss, :carbon_dioxide_loss, :ammonia_loss]
44
+
45
+ unless CHARGED_MODS.any? {|key| opts[key] > 0 }
46
+ puts "*" * 78
47
+ puts "ArgumentError: need at least one charged mod!"
48
+ puts "*" * 78
49
+ parser.educate
50
+ exit
51
+ end
52
+
53
+ (lipidmaps, *actual_mzs) = ARGV
54
+
55
+ if f=opts[:textfile]
56
+ actual_mzs = IO.readlines(f).map(&:chomp)
57
+ end
58
+
59
+ actual_mzs.map!(&:to_f)
60
+
61
+ unless actual_mzs.size > 0
62
+ STDERR.puts "NO m/z values given!!!"
63
+ parser.educate
64
+ exit
65
+ end
66
+
67
+ $VERBOSE = opts[:verbose]
68
+
69
+ LipidMod = Mspire::Lipid::Modification
70
+
71
+ mods = {
72
+ proton_gain: LipidMod.new(:proton),
73
+ water_loss: LipidMod.new(:water, :loss => true),
74
+ lithium: LipidMod.new(:lithium),
75
+ sodium: LipidMod.new(:sodium),
76
+ ammonium: LipidMod.new(:ammonium),
77
+ proton_loss: LipidMod.new(:proton, :loss => true),
78
+ ammonia_loss: LipidMod.new(:ammonium, :loss => true),
79
+ carbon_dioxide_loss: LipidMod.new(:carbon_dioxide, :loss => true),
80
+ }
81
+
82
+ lipids = Mspire::LipidMaps.parse_file(lipidmaps)
83
+
84
+ ions = []
85
+ lipids.each do |lipid|
86
+ CHARGED_MODS.each do |key|
87
+ if opts[key] > 0
88
+ opts[key].downto(1) do |num_charge_mod|
89
+ mods_to_use = [mods[key]] * num_charge_mod
90
+ UNCHARGED_MODS.each do |umod|
91
+ opts[umod].downto(0) do |i|
92
+ ions << Mspire::Lipid::Ion.new(lipid, mods_to_use + ([mods[umod]]*i))
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ ions.sort_by!(&:mz)
101
+
102
+ PPM = 1500
103
+
104
+ cats = %w(exp_mz rank ppm ppm_abs category lm_id common_name modifications)
105
+ puts cats.join("\t")
106
+
107
+ actual_mzs.sort! if opts[:sort]
108
+
109
+ starting_i = 0
110
+ len = ions.size
111
+
112
+ actual_mzs.each do |exp_mz|
113
+
114
+ range = ions.bsearch_range(starting_i...len) do |ion|
115
+ part_diff = ((exp_mz - ion.mz)/ion.mz)*1e6
116
+ if part_diff.abs <= PPM then 0
117
+ elsif part_diff < PPM then 1
118
+ else
119
+ -1
120
+ end
121
+ end
122
+
123
+ starting_i = range.begin if opts[:lower_bound]
124
+
125
+ closest = ions[range].sort_by {|ion| [(ion.mz - exp_mz).abs, ion.mz] }
126
+ row = [exp_mz]
127
+ closest[0,opts[:top_n]].each_with_index do |ion,i|
128
+ rank = i + 1
129
+ ppm = ((exp_mz - ion.mz) / ion.mz) * 1e6
130
+ lipid = ion.lipid
131
+ row.push( rank, ppm, ppm.abs, lipid.category, lipid.lm_id, lipid.common_name, ion.modifications.map(&:charged_formula_string).join(", ") )
132
+ end
133
+ puts row.join("\t")
134
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ require 'mspire/lipid'
4
+ require 'mspire/lipid/modification'
5
+ require 'mspire/lipid/ion'
6
+ require 'mspire/mass/element'
7
+ require 'mspire/mass/common'
8
+
9
+ module MSS
10
+ CO2 = ( %w(C O O).map {|e| Mspire::Mass::Element::MONO_STRING[e] }.reduce(:+) )
11
+ H2O = Mspire::Mass::Common::MONO_STRING['H2O']
12
+ PROTON_LOSS = Mspire::Lipid::Modification.new(:proton, :loss => true)
13
+ end
14
+
15
+
16
+ describe Mspire::Lipid::Ion do
17
+
18
+ before do
19
+ lipid = Mspire::Lipid.new("LMGP02010009", "PE(16:0/18:1(9Z))", "1-hexadecanoyl-2-(9Z-octadecenoyl)-sn-glycero-3-phosphoethanolamine", 'C39H76NO8P', 717.5308, 'Glycerophospholipids [GP]', 'Glycerophosphoethanolamines [GP02]', 'Diacylglycerophosphoethanolamines [GP0201]', '7850611', 'FHQVHHIBKUMWTI-OTMQOFQLSA-N')
20
+ proton = Mspire::Lipid::Modification.new(:proton)
21
+ proton_loss = Mspire::Lipid::Modification.new(:proton, :loss => true)
22
+ h2o_loss = Mspire::Lipid::Modification.new(:water, :loss => true)
23
+ @plus1_less_h20 = Mspire::Lipid::Ion.new(lipid, [proton, h2o_loss])
24
+ @plus2_less_h20 = Mspire::Lipid::Ion.new(lipid, [proton, proton, h2o_loss])
25
+ @minus1_less_h20 = Mspire::Lipid::Ion.new(lipid, [proton_loss, h2o_loss])
26
+ end
27
+
28
+ it 'calculates the correct m/z' do
29
+ @plus1_less_h20.mz.should be_within(1e-5).of(700.52751178307)
30
+ @plus2_less_h20.mz.should be_within(1e-5).of(350.76739412492003)
31
+ @minus1_less_h20.mz.should be_within(1e-5).of(698.5129588842301)
32
+ end
33
+
34
+ it 'calculates the correct formula' do
35
+ @plus1_less_h20.formula.to_s.should == "C39H75NO7P"
36
+ @plus1_less_h20.charge.should == 1
37
+
38
+ @plus2_less_h20.formula.to_s.should == "C39H76NO7P"
39
+ @plus2_less_h20.charge.should == 2
40
+ @minus1_less_h20.formula.to_s.should == "C39H73NO7P"
41
+ @minus1_less_h20.charge.should == -1
42
+ end
43
+
44
+ describe 'predicting ms/ms fragments' do
45
+ describe 'predicting simple fatty acyls' do
46
+ xit 'hexadecanoic acid' do
47
+ lipid = Mspire::Lipid.new('LMFA01010001', 'Palmitic acid', 'hexadecanoic acid', 'C16H32O2', 256.24, 'Fatty Acyls [FA]', 'Fatty Acids and Conjugates [FA01]', 'Straight chain fatty acids [FA0101]')
48
+
49
+ ion = Mspire::Lipid::Ion.new(lipid, [MSS::PROTON_LOSS])
50
+ frags = [ion.mz - MSS::H2O]
51
+ frags << ion.mz - MSS::CO2
52
+ frags << ion.mz - (MSS::H2O + MSS::CO2)
53
+
54
+ mzs = ion.predict_fragment_mzs
55
+ mzs.should be_an(Array)
56
+ mzs.sort.should == frags.sort
57
+ end
58
+
59
+ # WORKING THIS GUY OUT!!!!!!
60
+ xit '11-methyl-9S-hydroxy-13E-hexadecenoic acid' do
61
+ lipid = Mspire::Lipid.new(nil, 'Made Up', '11-methyl-9S-hydroxy-13E-hexadecenoic acid', 'C17H32O3', 284.23514488492003, 'Fatty Acyls [FA]', 'Fatty Acids and Conjugates [FA01]', 'Branched fatty acids [FA0102]')
62
+ ion = Mspire::Lipid::Ion.new(lipid, [MSS::PROTON_LOSS])
63
+
64
+ # one water loss
65
+ frags = [ion.mz - MSS::H2O]
66
+
67
+ # two water loss
68
+ frags << (ion.mz - (2*MSS::H2O))
69
+
70
+ # CO2 loss
71
+ frags << (ion.mz - MSS::CO2)
72
+
73
+ # CO2 + H20 loss
74
+ frags << ion.mz - (MSS::H2O + MSS::CO2)
75
+
76
+ oh_frag_mass = 140.12011513268
77
+ frag1 = (ion.mz - oh_frag_mass)
78
+
79
+ frags << frag1 - MSS::H2O
80
+
81
+ frags << frag1 - MSS::CO2
82
+
83
+ frags << frag1 - (MSS::H2O + MSS::CO2)
84
+
85
+ mzs = ion.predict_fragment_mzs
86
+ #mzs.sort.should == frags.sort
87
+ end
88
+
89
+ end
90
+
91
+ it 'predicts simple glycerophosopholipids' do
92
+ end
93
+
94
+ end
95
+
96
+ end