ProteoWizard
RAMPAdapterTest.cpp
Go to the documentation of this file.
1 //
2 // $Id: RAMPAdapterTest.cpp 4129 2012-11-20 00:05:37Z chambm $
3 //
4 //
5 // Original author: Darren Kessner <darren@proteowizard.org>
6 //
7 // Copyright 2008 Spielberg Family Center for Applied Proteomics
8 // Cedars-Sinai Medical Center, Los Angeles, California 90048
9 //
10 // Licensed under the Apache License, Version 2.0 (the "License");
11 // you may not use this file except in compliance with the License.
12 // You may obtain a copy of the License at
13 //
14 // http://www.apache.org/licenses/LICENSE-2.0
15 //
16 // Unless required by applicable law or agreed to in writing, software
17 // distributed under the License is distributed on an "AS IS" BASIS,
18 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 // See the License for the specific language governing permissions and
20 // limitations under the License.
21 //
22 
23 
24 #include "RAMPAdapter.hpp"
25 #include "MSDataFile.hpp"
26 #include "examples.hpp"
30 #include <boost/iostreams/filtering_stream.hpp>
31 #include <boost/iostreams/filter/gzip.hpp>
32 #include <boost/iostreams/device/file_descriptor.hpp>
33 #include <boost/iostreams/copy.hpp>
34 
35 
36 using namespace pwiz::cv;
37 using namespace pwiz::msdata;
38 using namespace pwiz::util;
39 
40 
41 ostream* os_ = 0;
42 
43 /*
44 RAMP will need to instantiate an msdata::RAMPAdapter object, and call it to fill
45 in the appropriate RAMP structures:
46 
47  using namespace pwiz;
48 using namespace pwiz::msdata;
49 
50  RAMPAdapter adapter("something.mzML");
51 
52  unsigned int scanIndex = rampAdapter.index(19); // get index for scan 19
53 
54  ScanHeaderStruct temp;
55  adapter.getScanHeader(scanIndex, temp);
56 
57  vector<double> buffer;
58  adapter.getScanPeaks(scanIndex, buffer);
59 
60  RunHeaderStruct temp2;
61  adapter.getRunHeader(temp2);
62 
63  InstrumentHeaderStruct temp3;
64  adapter.getInstrumentHeader(temp3);
65 
66 Note that the MSData library can throw exceptions, so the RAMP code will have to be able
67 to handle these gracefully. Another option is to have these RAMPAdapter functions catch
68 any exceptions and return an error code if something goes wrong.
69 */
70 
71 
72 string writeTempFile()
73 {
74  const string& filename = "temp.RAMPAdapterTest.tiny.mzML";
75  MSData tiny;
77  MSDataFile::write(tiny, filename);
78  return filename;
79 }
80 
81 
82 ostream& operator<<(ostream& os, const ScanHeaderStruct& header)
83 {
84  os << "seqNum: " << header.seqNum << endl;
85  os << "acquisitionNum: " << header.acquisitionNum << endl;
86  os << "msLevel: " << header.msLevel << endl;
87  os << "peaksCount: " << header.peaksCount << endl;
88  os << "totIonCurrent: " << header.totIonCurrent << endl;
89  os << "retentionTime: " << header.retentionTime << endl;
90  os << "basePeakMZ: " << header.basePeakMZ << endl;
91  os << "basePeakIntensity: " << header.basePeakIntensity << endl;
92  os << "collisionEnergy: " << header.collisionEnergy << endl;
93  os << "ionisationEnergy: " << header.ionisationEnergy << endl;
94  os << "lowMZ: " << header.lowMZ << endl;
95  os << "highMZ: " << header.highMZ << endl;
96  os << "precursorScanNum: " << header.precursorScanNum << endl;
97  os << "precursorMZ: " << header.precursorMZ << endl;
98  os << "precursorCharge: " << header.precursorCharge << endl;
99  os << "precursorIntensity: " << header.precursorIntensity << endl;
100  os << "scanType: " << header.scanType << endl;
101  os << "mergedScan: " << header.mergedScan << endl;
102  os << "mergedResultScanNum: " << header.mergedResultScanNum << endl;
103  os << "mergedResultStartScanNum: " << header.mergedResultStartScanNum << endl;
104  os << "mergedResultEndScanNum: " << header.mergedResultEndScanNum << endl;
105  os << "filePosition: " << header.filePosition << endl;
106  return os;
107 }
108 
109 
110 ostream& operator<<(ostream& os, const RunHeaderStruct& header)
111 {
112  os << "scanCount: " << header.scanCount << endl;
113  os << "lowMZ: " << header.lowMZ << endl;
114  os << "highMZ: " << header.highMZ << endl;
115  os << "startMZ: " << header.startMZ << endl;
116  os << "endMZ: " << header.endMZ << endl;
117  os << "dStartTime: " << header.dStartTime << endl;
118  os << "dEndTime: " << header.dEndTime << endl;
119  return os;
120 }
121 
122 
123 ostream& operator<<(ostream& os, const InstrumentStruct& instrument)
124 {
125  os << "manufacturer: " << instrument.manufacturer << endl;
126  os << "model: " << instrument.model << endl;
127  os << "ionisation: " << instrument.ionisation << endl;
128  os << "analyzer: " << instrument.analyzer << endl;
129  os << "detector: " << instrument.detector << endl;
130  return os;
131 }
132 
133 
134 void test(const string& filename)
135 {
136  RAMPAdapter adapter(filename);
137 
138  size_t scanCount = adapter.scanCount();
139  if (os_) *os_ << "scanCount: " << scanCount << "\n\n";
140  unit_assert(scanCount == 5);
141 
142  unit_assert(adapter.index(19) == 0);
143  unit_assert(adapter.index(20) == 1);
144  unit_assert(adapter.index(21) == 2);
145 
146  // first scan (scan number == 19)
147 
148  ScanHeaderStruct header1;
149  adapter.getScanHeader(0, header1);
150  if (os_) *os_ << header1;
151  unit_assert(header1.seqNum == 1);
152  unit_assert(header1.acquisitionNum == 19);
153  unit_assert(header1.msLevel == 1);
154  unit_assert(header1.peaksCount == 15);
155  const double epsilon = 1e-8;
156  unit_assert_equal(header1.totIonCurrent, 1.66755e7, epsilon);
157  unit_assert_equal(header1.retentionTime, 353.43, epsilon);
158  unit_assert_equal(header1.basePeakMZ, 445.347, epsilon);
159  unit_assert_equal(header1.basePeakIntensity, 120053, epsilon);
160  unit_assert_equal(header1.collisionEnergy, 0., epsilon);
161  unit_assert_equal(header1.lowMZ, 400.39, epsilon);
162  unit_assert_equal(header1.highMZ, 1795.56, epsilon);
163  unit_assert(header1.precursorScanNum == 0);
164  unit_assert(header1.scanType == string("Full"));
165 
166  vector<double> peaks;
167  adapter.getScanPeaks(0, peaks);
168  unit_assert(peaks.size() == 30);
169  if (os_)
170  {
171  const MZIntensityPair* begin = reinterpret_cast<const MZIntensityPair*>(&peaks[0]);
172  copy(begin, begin+15, ostream_iterator<MZIntensityPair>(*os_, "\n"));
173  *os_ << endl;
174  }
175 
176  // second scan (scan number == 20)
177 
178  ScanHeaderStruct header2;
179  adapter.getScanHeader(1, header2);
180  if (os_) *os_ << header2;
181  unit_assert(header2.seqNum == 2);
182  unit_assert(header2.acquisitionNum == 20);
183  unit_assert(header2.msLevel == 2);
184  unit_assert(header2.peaksCount == 10);
185  unit_assert_equal(header2.totIonCurrent, 1.66755e7, epsilon);
186  unit_assert_equal(header2.retentionTime, 359.43, epsilon);
187  unit_assert_equal(header2.basePeakMZ, 456.347, epsilon);
188  unit_assert_equal(header2.basePeakIntensity, 23433, epsilon);
189  unit_assert_equal(header2.collisionEnergy, 35, epsilon);
190  unit_assert_equal(header2.lowMZ, 320.39, epsilon);
191  unit_assert_equal(header2.highMZ, 1003.56, epsilon);
192  unit_assert(header2.precursorScanNum == 19);
193  unit_assert_equal(header2.precursorMZ, 445.34, epsilon);
194  unit_assert(header2.precursorCharge == 2);
195  unit_assert_equal(header2.precursorIntensity, 120053, epsilon);
196  unit_assert(header2.scanType == string("Full"));
197 
198  adapter.getScanPeaks(1, peaks);
199  unit_assert(peaks.size() == 20);
200  if (os_)
201  {
202  const MZIntensityPair* begin = reinterpret_cast<const MZIntensityPair*>(&peaks[0]);
203  copy(begin, begin+10, ostream_iterator<MZIntensityPair>(*os_, "\n"));
204  *os_ << endl;
205  }
206 
207  // last scan
208 
209  ScanHeaderStruct header5;
210  adapter.getScanHeader(4, header5);
211  if (os_) *os_ << header5;
212 
213  // RunHeader
214 
215  RunHeaderStruct runHeader;
216  adapter.getRunHeader(runHeader);
217  unit_assert(runHeader.scanCount == 5);
218  unit_assert(runHeader.lowMZ == 0);
219  unit_assert(runHeader.highMZ == 0);
220  unit_assert(runHeader.startMZ == 0);
221  unit_assert(runHeader.endMZ == 0);
222  unit_assert_equal(runHeader.dStartTime, header1.retentionTime, 1e-6);
223  unit_assert_equal(runHeader.dEndTime, header5.retentionTime, 1e-6);
224 
225  if (os_)
226  *os_ << "RunHeader:\n" << runHeader << endl;
227 
228  // Instrument
229  InstrumentStruct instrument;
230  adapter.getInstrument(instrument);
231  if (os_)
232  *os_ << "Instrument:\n" << instrument << endl;
233 
234  unit_assert(!strcmp(instrument.manufacturer, "Thermo Finnigan"));
235  unit_assert(!strcmp(instrument.model, "LCQ Deca"));
236  unit_assert(!strcmp(instrument.ionisation, "nanoelectrospray"));
237  unit_assert(!strcmp(instrument.analyzer, "quadrupole ion trap"));
238  unit_assert(!strcmp(instrument.detector, "electron multiplier"));
239 }
240 
241 static void test_mzML_1_0(const char *test_app_name) {
242  // depending on where you invoke bjam from, test_app_name will have name like...
243  // ..\build\pwiz\data\msdata\gcc-mingw-3.4.5\release\link-static\runtime-link-static\threading-multi\RAMPAdapterTest.exe
244  // build\pwiz\data\msdata\gcc-mingw-3.4.5\release\link-static\runtime-link-static\threading-multi\RAMPAdapterTest.exe
245  std::string buildparent(test_app_name);
246  size_t pos = buildparent.find("build");
247  if (pos == std::string::npos) {
248  buildparent = __FILE__; // nonstandard build, maybe? try using source file name
249  // something like \ProteoWizard\pwiz\pwiz\data\msdata\RAMPAdapterTest.cpp
250  pos = buildparent.rfind("pwiz");
251  }
252  buildparent.resize(pos);
253  std::string example_data_dir = buildparent + "example_data/";
254  RAMPAdapter adapter_1_0(example_data_dir + "tiny.pwiz.1.0.mzML");
255  const char *testfiles[2] = {"tiny.pwiz.1.1.mzML","tiny.pwiz.mzXML"};
256  for (int tf=2;tf--;) { // test mzML 1.0 vs mzML 1.1 and mzXML
257  RAMPAdapter adapter_1_1(example_data_dir + testfiles[tf]);
258 
259  // tiny example has 4 spectra, the last of which is non-default source -- test scans 1,2,3 only
260  unit_assert(adapter_1_0.scanCount() == adapter_1_1.scanCount());
261  for (int scan=4;scan--;) {
262  ScanHeaderStruct header1_0, header1_1;
263  adapter_1_0.getScanHeader(scan, header1_0);
264  adapter_1_1.getScanHeader(scan, header1_1);
265  unit_assert(header1_0.seqNum == header1_1.seqNum );
266  if (scan < 3) {
267  unit_assert(header1_0.acquisitionNum == header1_1.acquisitionNum );
268  }
269  unit_assert(header1_0.msLevel == header1_1.msLevel );
270  unit_assert(header1_0.peaksCount == header1_1.peaksCount );
271  const double epsilon = 1e-6;
272  unit_assert_equal(header1_0.totIonCurrent, header1_1.totIonCurrent, epsilon);
273  unit_assert_equal(header1_0.retentionTime, header1_1.retentionTime, epsilon);
274  unit_assert_equal(header1_0.basePeakMZ, header1_1.basePeakMZ, epsilon);
275  unit_assert_equal(header1_0.basePeakIntensity, header1_1.basePeakIntensity, epsilon);
276  unit_assert_equal(header1_0.collisionEnergy, header1_1.collisionEnergy, epsilon);
277  unit_assert_equal(header1_0.lowMZ, header1_1.lowMZ, epsilon);
278  unit_assert_equal(header1_0.highMZ, header1_1.highMZ, epsilon);
279  unit_assert(header1_0.precursorScanNum == header1_1.precursorScanNum );
280  }
281  }
282 }
283 
284 int main(int argc, char* argv[])
285 {
286  TEST_PROLOG(argc, argv)
287 
288  try
289  {
290  if (argc>1 && !strcmp(argv[1],"-v")) os_ = &cout;
291  string filename = writeTempFile();
292  test(filename);
293 
294  // now try it with a gzipped file
295  string gzfilename = filename + ".gz";
296  bio::filtering_istream tinyGZ(bio::gzip_compressor() | bio::file_descriptor_source(filename));
297  bio::copy(tinyGZ, bio::file_descriptor_sink(gzfilename, ios::out|ios::binary));
298  test(gzfilename);
299 
300  boost::filesystem::remove(filename);
301  boost::filesystem::remove(gzfilename);
302  // and make sure we're still good with older files
303  test_mzML_1_0(argv[0]); // passing in app name as it contains our path
304 
305  }
306  catch (exception& e)
307  {
308  TEST_FAILED(e.what())
309  }
310  catch (...)
311  {
312  TEST_FAILED("Caught unknown exception.")
313  }
314 
316 }
317 
318