Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages

MzMLHandler.h

Go to the documentation of this file.
00001 // --------------------------------------------------------------------------
00002 //                   OpenMS -- Open-Source Mass Spectrometry
00003 // --------------------------------------------------------------------------
00004 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
00005 // ETH Zurich, and Freie Universitaet Berlin 2002-2012.
00006 //
00007 // This software is released under a three-clause BSD license:
00008 //  * Redistributions of source code must retain the above copyright
00009 //    notice, this list of conditions and the following disclaimer.
00010 //  * Redistributions in binary form must reproduce the above copyright
00011 //    notice, this list of conditions and the following disclaimer in the
00012 //    documentation and/or other materials provided with the distribution.
00013 //  * Neither the name of any author or any participating institution
00014 //    may be used to endorse or promote products derived from this software
00015 //    without specific prior written permission.
00016 // For a full list of authors, refer to the file AUTHORS.
00017 // --------------------------------------------------------------------------
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
00022 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00025 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00027 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 //
00030 // --------------------------------------------------------------------------
00031 // $Maintainer: Andreas Bertsch $
00032 // $Authors: Marc Sturm $
00033 // --------------------------------------------------------------------------
00034 
00035 #ifndef OPENMS_FORMAT_HANDLERS_MZMLHANDLER_H
00036 #define OPENMS_FORMAT_HANDLERS_MZMLHANDLER_H
00037 
00038 #include <OpenMS/CONCEPT/Exception.h>
00039 #include <OpenMS/CONCEPT/ProgressLogger.h>
00040 #include <OpenMS/FORMAT/HANDLERS/XMLHandler.h>
00041 #include <OpenMS/FORMAT/VALIDATORS/MzMLValidator.h>
00042 #include <OpenMS/FORMAT/OPTIONS/PeakFileOptions.h>
00043 #include <OpenMS/FORMAT/Base64.h>
00044 #include <OpenMS/KERNEL/MSExperiment.h>
00045 #include <OpenMS/FORMAT/VALIDATORS/SemanticValidator.h>
00046 #include <OpenMS/FORMAT/CVMappingFile.h>
00047 #include <OpenMS/DATASTRUCTURES/CVMappings.h>
00048 #include <OpenMS/FORMAT/ControlledVocabulary.h>
00049 #include <OpenMS/SYSTEM/File.h>
00050 
00051 #include <sstream>
00052 #include <iostream>
00053 
00054 
00055 #include <QtCore/QRegExp>
00056 
00057 //MISSING:
00058 // - more than one selected ion per precursor (warning if more than one)
00059 // - scanWindowList for each acquisition separately (currently for the whole spectrum only)
00060 // - instrumentConfigurationRef attribute for scan (why should the instrument change between scans? - warning if used)
00061 // - scanSettingsRef attribute for instrumentConfiguration tag (currently no information there because of missing mapping file entry - warning if used)
00062 
00063 // xs:id/xs:idref prefix list
00064 // - sf_ru : sourceFile (run)
00065 // - sf_sp : sourceFile (spectrum)
00066 // - sf_pr : sourceFile (precursor)
00067 // - sf_ac : sourceFile (acquisition)
00068 // - sa    : sample
00069 // - ic    : instrumentConfiguration
00070 // - so_dp : software (data processing)
00071 // - so_in : software (instrument)
00072 // - dp_sp : dataProcessing (spectrum)
00073 // - dp_bi : dataProcessing (binary data array)
00074 // - dp_ch : dataProcessing (chromatogram)
00075 
00076 namespace OpenMS
00077 {
00078   class ControlledVocabulary;
00079   class CVMappingFile;
00080   class CVMappings;
00081   namespace Internal
00082   {
00083 
00091     template <typename MapType>
00092     class MzMLHandler :
00093       public XMLHandler
00094     {
00095 public:
00098 
00099       MzMLHandler(MapType& exp, const String& filename, const String& version, ProgressLogger& logger) :
00100         XMLHandler(filename, version),
00101         exp_(&exp),
00102         cexp_(0),
00103         options_(),
00104         spec_(),
00105         chromatogram_(),
00106         data_(),
00107         default_array_length_(0),
00108         in_spectrum_list_(false),
00109         decoder_(),
00110         logger_(logger),
00111         skip_spectrum_(false) /* ,
00112                 validator_(mapping_, cv_) */
00113       {
00114         cv_.loadFromOBO("MS", File::find("/CV/psi-ms.obo"));
00115         cv_.loadFromOBO("PATO", File::find("/CV/quality.obo"));
00116         cv_.loadFromOBO("UO", File::find("/CV/unit.obo"));
00117         cv_.loadFromOBO("BTO", File::find("/CV/brenda.obo"));
00118         cv_.loadFromOBO("GO", File::find("/CV/goslim_goa.obo"));
00119 
00120         CVMappingFile().load(File::find("/MAPPING/ms-mapping.xml"), mapping_);
00121         //~ validator_ = Internal::MzMLValidator(mapping_, cv_);
00122       }
00123 
00125       MzMLHandler(const MapType& exp, const String& filename, const String& version, const ProgressLogger& logger) :
00126         XMLHandler(filename, version),
00127         exp_(0),
00128         cexp_(&exp),
00129         options_(),
00130         spec_(),
00131         chromatogram_(),
00132         data_(),
00133         default_array_length_(0),
00134         in_spectrum_list_(false),
00135         decoder_(),
00136         logger_(logger),
00137         skip_spectrum_(false) /* ,
00138                 validator_(mapping_, cv_) */
00139       {
00140         cv_.loadFromOBO("MS", File::find("/CV/psi-ms.obo"));
00141         cv_.loadFromOBO("PATO", File::find("/CV/quality.obo"));
00142         cv_.loadFromOBO("UO", File::find("/CV/unit.obo"));
00143         cv_.loadFromOBO("BTO", File::find("/CV/brenda.obo"));
00144         cv_.loadFromOBO("GO", File::find("/CV/goslim_goa.obo"));
00145 
00146         CVMappingFile().load(File::find("/MAPPING/ms-mapping.xml"), mapping_);
00147         //~ validator_ = Internal::MzMLValidator(mapping_, cv_);
00148       }
00149 
00151       virtual ~MzMLHandler()
00152       {
00153       }
00154 
00156 
00157 
00158       // Docu in base class
00159       virtual void endElement(const XMLCh* const /*uri*/, const XMLCh* const /*local_name*/, const XMLCh* const qname);
00160 
00161       // Docu in base class
00162       virtual void startElement(const XMLCh* const /*uri*/, const XMLCh* const /*local_name*/, const XMLCh* const qname, const xercesc::Attributes& attributes);
00163 
00164       // Docu in base class
00165       virtual void characters(const XMLCh* const chars, const XMLSize_t length);
00166 
00167       //Docu in base class
00168       virtual void writeTo(std::ostream& os);
00169 
00170       void setOptions(const PeakFileOptions& opt)
00171       {
00172         options_ = opt;
00173       }
00174 
00175 protected:
00176 
00178       typedef typename MapType::PeakType PeakType;
00180       typedef typename MapType::ChromatogramPeakType ChromatogramPeakType;
00182       typedef MSSpectrum<PeakType> SpectrumType;
00184       typedef MSChromatogram<ChromatogramPeakType> ChromatogramType;
00185 
00187       struct BinaryData
00188       {
00189         String base64;
00190         enum {PRE_NONE, PRE_32, PRE_64} precision;
00191         Size size;
00192         bool compression;
00193         enum {DT_NONE, DT_FLOAT, DT_INT, DT_STRING} data_type;
00194         std::vector<Real> floats_32;
00195         std::vector<DoubleReal> floats_64;
00196         std::vector<Int32> ints_32;
00197         std::vector<Int64> ints_64;
00198         std::vector<String> decoded_char;
00199         MetaInfoDescription meta;
00200       };
00201 
00203       MapType* exp_;
00205       const MapType* cexp_;
00206 
00208       PeakFileOptions options_;
00209 
00212 
00213       SpectrumType spec_;
00215       ChromatogramType chromatogram_;
00217       std::vector<BinaryData> data_;
00219       Size default_array_length_;
00221       bool in_spectrum_list_;
00223       String current_id_;
00225       Map<String, std::vector<SemanticValidator::CVTerm> > ref_param_;
00227       Map<String, SourceFile> source_files_;
00229       Map<String, Sample> samples_;
00231       Map<String, Software> software_;
00233       Map<String, Instrument> instruments_;
00235       Map<String, std::vector<DataProcessing> > processing_;
00237       String default_processing_;
00239 
00241       Base64 decoder_;
00242 
00244       const ProgressLogger& logger_;
00245 
00247       bool skip_spectrum_;
00248 
00250       ControlledVocabulary cv_;
00251       CVMappings mapping_;
00252       //~ Internal::MzMLValidator validator_;
00253 
00255       UInt selected_ion_count_;
00256 
00258       void fillData_();
00259 
00261       void fillChromatogramData_();
00262 
00264       void handleCVParam_(const String& parent_parent_tag, const String& parent_tag, /*  const String & cvref, */ const String& accession, const String& name, const String& value, const String& unit_accession = "");
00265 
00267       void handleUserParam_(const String& parent_parent_tag, const String& parent_tag, const String& name, const String& type, const String& value);
00268 
00270       void writeUserParam_(std::ostream& os, const MetaInfoInterface& meta, UInt indent, String path, Internal::MzMLValidator& validator) const;
00271 
00273       ControlledVocabulary::CVTerm getChildWithName_(const String& parent_accession, const String& name) const;
00274 
00276       void writeSoftware_(std::ostream& os, const String& id, const Software& software, Internal::MzMLValidator& validator);
00277 
00279       void writeSourceFile_(std::ostream& os, const String& id, const SourceFile& software, Internal::MzMLValidator& validator);
00280 
00282       void writeDataProcessing_(std::ostream& os, const String& id, const std::vector<DataProcessing>& dps, Internal::MzMLValidator& validator);
00283 
00285       void writePrecursor_(std::ostream& os, const Precursor& precursor, Internal::MzMLValidator& validator);
00286 
00288       void writeProduct_(std::ostream& os, const Product& product, Internal::MzMLValidator& validator);
00289 
00291       String writeCV_(const ControlledVocabulary::CVTerm& c, const DataValue& metaValue) const;
00292 
00294       bool validateCV_(const ControlledVocabulary::CVTerm& c, const String& path, const Internal::MzMLValidator& validator) const;
00295     };
00296 
00297     //--------------------------------------------------------------------------------
00298 
00299     template <typename MapType>
00300     void MzMLHandler<MapType>::characters(const XMLCh* const chars, const XMLSize_t /*length*/)
00301     {
00302       if (skip_spectrum_)
00303         return;
00304 
00305       char* transcoded_chars = sm_.convert(chars);
00306 
00307       String& current_tag = open_tags_.back();
00308 
00309       if (current_tag == "binary" /* && in_spectrum_list_*/)
00310       {
00311         //chars may be split to several chunks => concatenate them
00312         data_.back().base64 += transcoded_chars;
00313       }
00314       else if (current_tag == "offset" || current_tag == "indexListOffset" || current_tag == "fileChecksum" /* || current_tag == "binary"*/)
00315       {
00316         //do nothing for
00317         // - index
00318         // - checksum
00319         // - binary chromatogram data
00320       }
00321       else
00322       {
00323         String transcoded_chars2 = transcoded_chars;
00324         transcoded_chars2.trim();
00325         if (transcoded_chars2 != "")
00326           warning(LOAD, String("Unhandled character content in tag '") + current_tag + "': " + transcoded_chars2);
00327       }
00328     }
00329 
00330     template <typename MapType>
00331     void MzMLHandler<MapType>::startElement(const XMLCh* const /*uri*/, const XMLCh* const /*local_name*/, const XMLCh* const qname, const xercesc::Attributes& attributes)
00332     {
00333       static const XMLCh* s_count = xercesc::XMLString::transcode("count");
00334       static const XMLCh* s_default_array_length = xercesc::XMLString::transcode("defaultArrayLength");
00335       static const XMLCh* s_array_length = xercesc::XMLString::transcode("arrayLength");
00336       static const XMLCh* s_accession = xercesc::XMLString::transcode("accession");
00337       static const XMLCh* s_name = xercesc::XMLString::transcode("name");
00338       static const XMLCh* s_type = xercesc::XMLString::transcode("type");
00339       static const XMLCh* s_value = xercesc::XMLString::transcode("value");
00340       static const XMLCh* s_unit_accession = xercesc::XMLString::transcode("unitAccession");
00341       static const XMLCh* s_id = xercesc::XMLString::transcode("id");
00342       static const XMLCh* s_spot_id = xercesc::XMLString::transcode("spotID");
00343       //~ static const XMLCh * s_cvref = xercesc::XMLString::transcode("cvRef"); TODO
00344       static const XMLCh* s_ref = xercesc::XMLString::transcode("ref");
00345       static const XMLCh* s_version = xercesc::XMLString::transcode("version");
00346       static const XMLCh* s_order = xercesc::XMLString::transcode("order");
00347       static const XMLCh* s_location = xercesc::XMLString::transcode("location");
00348       static const XMLCh* s_sample_ref = xercesc::XMLString::transcode("sampleRef");
00349       static const XMLCh* s_software_ref = xercesc::XMLString::transcode("softwareRef");
00350       static const XMLCh* s_source_file_ref = xercesc::XMLString::transcode("sourceFileRef");
00351       static const XMLCh* s_default_instrument_configuration_ref = xercesc::XMLString::transcode("defaultInstrumentConfigurationRef");
00352       static const XMLCh* s_instrument_configuration_ref = xercesc::XMLString::transcode("instrumentConfigurationRef");
00353       static const XMLCh* s_default_data_processing_ref = xercesc::XMLString::transcode("defaultDataProcessingRef");
00354       static const XMLCh* s_data_processing_ref = xercesc::XMLString::transcode("dataProcessingRef");
00355       static const XMLCh* s_start_time_stamp = xercesc::XMLString::transcode("startTimeStamp");
00356       static const XMLCh* s_external_spectrum_id = xercesc::XMLString::transcode("externalSpectrumID");
00357       static const XMLCh* s_default_source_file_ref = xercesc::XMLString::transcode("defaultSourceFileRef");
00358       static const XMLCh* s_scan_settings_ref = xercesc::XMLString::transcode("scanSettingsRef");
00359 
00360       String tag = sm_.convert(qname);
00361       open_tags_.push_back(tag);
00362 
00363       //determine parent tag
00364       String parent_tag;
00365       if (open_tags_.size() > 1)
00366         parent_tag = *(open_tags_.end() - 2);
00367       String parent_parent_tag;
00368       if (open_tags_.size() > 2)
00369         parent_parent_tag = *(open_tags_.end() - 3);
00370 
00371       //do nothing until a new spectrum is reached
00372       if (tag != "spectrum" && skip_spectrum_)
00373         return;
00374 
00375       if (tag == "spectrum")
00376       {
00377         //number of peaks
00378         spec_ = SpectrumType();
00379         default_array_length_ = attributeAsInt_(attributes, s_default_array_length);
00380         //spectrum source file
00381         String source_file_ref;
00382         if (optionalAttributeAsString_(source_file_ref, attributes, s_source_file_ref))
00383         {
00384           spec_.setSourceFile(source_files_[source_file_ref]);
00385         }
00386         //native id
00387         spec_.setNativeID(attributeAsString_(attributes, s_id));
00388         //maldi spot id
00389         String maldi_spot_id;
00390         if (optionalAttributeAsString_(maldi_spot_id, attributes, s_spot_id))
00391         {
00392           spec_.setMetaValue("maldi_spot_id", maldi_spot_id);
00393         }
00394         //data processing
00395         String data_processing_ref;
00396         if (optionalAttributeAsString_(data_processing_ref, attributes, s_data_processing_ref))
00397         {
00398           spec_.setDataProcessing(processing_[data_processing_ref]);
00399         }
00400         else
00401         {
00402           spec_.setDataProcessing(processing_[default_processing_]);
00403         }
00404       }
00405       else if (tag == "chromatogram")
00406       {
00407         chromatogram_ = ChromatogramType();
00408         default_array_length_ = attributeAsInt_(attributes, s_default_array_length);
00409         String source_file_ref;
00410         if (optionalAttributeAsString_(source_file_ref, attributes, s_source_file_ref))
00411         {
00412           chromatogram_.setSourceFile(source_files_[source_file_ref]);
00413         }
00414         // native id
00415         chromatogram_.setNativeID(attributeAsString_(attributes, s_id));
00416         // data processing
00417         String data_processing_ref;
00418         if (optionalAttributeAsString_(data_processing_ref, attributes, s_data_processing_ref))
00419         {
00420           chromatogram_.setDataProcessing(processing_[data_processing_ref]);
00421         }
00422         else
00423         {
00424           chromatogram_.setDataProcessing(processing_[default_processing_]);
00425         }
00426       }
00427       else if (tag == "spectrumList")
00428       {
00429         //default data processing
00430         default_processing_ = attributeAsString_(attributes, s_default_data_processing_ref);
00431 
00432         //Abort if we need meta data only
00433         if (options_.getMetadataOnly())
00434           throw EndParsingSoftly(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00435 
00436         UInt count = attributeAsInt_(attributes, s_count);
00437         exp_->reserve(count);
00438         logger_.startProgress(0, count, "loading mzML file");
00439         in_spectrum_list_ = true;
00440       }
00441       else if (tag == "chromatogramList")
00442       {
00443         // default data processing
00444         default_processing_ = attributeAsString_(attributes, s_default_data_processing_ref);
00445 
00446         //Abort if we need meta data only
00447         if (options_.getMetadataOnly())
00448           throw EndParsingSoftly(__FILE__, __LINE__, __PRETTY_FUNCTION__);
00449 
00450         UInt count = attributeAsInt_(attributes, s_count);
00451         // do not reserve vector, simply do push_back
00452         logger_.startProgress(0, count, "loading chromatograms");
00453         in_spectrum_list_ = false;
00454       }
00455       else if (tag == "binaryDataArrayList" /* && in_spectrum_list_*/)
00456       {
00457         data_.reserve(attributeAsInt_(attributes, s_count));
00458       }
00459       else if (tag == "binaryDataArray" /* && in_spectrum_list_*/)
00460       {
00461         data_.push_back(BinaryData());
00462 
00463         //array length
00464         Int array_length = (Int) default_array_length_;
00465         optionalAttributeAsInt_(array_length, attributes, s_array_length);
00466         data_.back().size = array_length;
00467 
00468         //data processing
00469         String data_processing_ref;
00470         if (optionalAttributeAsString_(data_processing_ref, attributes, s_data_processing_ref))
00471         {
00472           data_.back().meta.setDataProcessing(processing_[data_processing_ref]);
00473         }
00474         else
00475         {
00476           data_.back().meta.setDataProcessing(processing_[data_processing_ref]);
00477         }
00478       }
00479       else if (tag == "cvParam")
00480       {
00481         String value = "";
00482         optionalAttributeAsString_(value, attributes, s_value);
00483         String unit_accession = "";
00484         optionalAttributeAsString_(unit_accession, attributes, s_unit_accession);
00485         handleCVParam_(parent_parent_tag, parent_tag, /* attributeAsString_(attributes, s_cvref), */ attributeAsString_(attributes, s_accession), attributeAsString_(attributes, s_name), value, unit_accession);
00486       }
00487       else if (tag == "userParam")
00488       {
00489         String type = "";
00490         optionalAttributeAsString_(type, attributes, s_type);
00491         String value = "";
00492         optionalAttributeAsString_(value, attributes, s_value);
00493         handleUserParam_(parent_parent_tag, parent_tag, attributeAsString_(attributes, s_name), type, value);
00494       }
00495       else if (tag == "referenceableParamGroup")
00496       {
00497         current_id_ = attributeAsString_(attributes, s_id);
00498       }
00499       else if (tag == "sourceFile")
00500       {
00501         current_id_ = attributeAsString_(attributes, s_id);
00502         source_files_[current_id_].setNameOfFile(attributeAsString_(attributes, s_name));
00503         source_files_[current_id_].setPathToFile(attributeAsString_(attributes, s_location));
00504       }
00505       else if (tag == "referenceableParamGroupRef")
00506       {
00507         //call handleCVParam_ with the parent tag for each parameter in the group
00508         String ref = attributeAsString_(attributes, s_ref);
00509         for (Size i = 0; i < ref_param_[ref].size(); ++i)
00510         {
00511           handleCVParam_(parent_parent_tag, parent_tag, /* attributeAsString_(attributes, s_cvref), */ ref_param_[ref][i].accession, ref_param_[ref][i].name, ref_param_[ref][i].value, ref_param_[ref][i].unit_accession);
00512         }
00513       }
00514       else if (tag == "scan")
00515       {
00516         Acquisition tmp;
00517         //source file => meta data
00518         String source_file_ref;
00519         if (optionalAttributeAsString_(source_file_ref, attributes, s_source_file_ref))
00520         {
00521           tmp.setMetaValue("source_file_name", source_files_[source_file_ref].getNameOfFile());
00522           tmp.setMetaValue("source_file_path", source_files_[source_file_ref].getPathToFile());
00523         }
00524         //external spectrum id => meta data
00525         String external_spectrum_id;
00526         if (optionalAttributeAsString_(external_spectrum_id, attributes, s_external_spectrum_id))
00527         {
00528           tmp.setIdentifier(external_spectrum_id);
00529         }
00530 
00531         //spectrumRef - not really needed
00532 
00533         //instrumentConfigurationRef - not really needed: why should a scan have a different instrument?
00534         String instrument_configuration_ref;
00535         if (optionalAttributeAsString_(instrument_configuration_ref, attributes, s_instrument_configuration_ref))
00536         {
00537           warning(LOAD, "Unhandled attribute 'instrumentConfigurationRef' in 'scan' tag.");
00538         }
00539 
00540         spec_.getAcquisitionInfo().push_back(tmp);
00541       }
00542       else if (tag == "mzML")
00543       {
00544         //check file version against schema version
00545         String file_version = attributeAsString_(attributes, s_version);
00546         if (!file_version.toQString().contains(QRegExp("^1.\\d+.\\d+$")))
00547         {
00548           warning(LOAD, String("Invalid mzML version string '") + file_version + "'. Assuming mzML version " + version_ + "!");
00549         }
00550 
00551         DoubleReal double_version = 0.0;
00552         try
00553         {
00554           double_version = file_version.toDouble();
00555         }
00556         catch (...)
00557         {
00558           //nothing to do here
00559         }
00560         if (double_version >= 1.0 && double_version < 1.1)
00561         {
00562           fatalError(LOAD, String("Only mzML 1.1.0 or higher is supported! This file has version '") + file_version + "'.");
00563         }
00564         else if (double_version > version_.toDouble())
00565         {
00566           warning(LOAD, "The mzML file version (" + file_version + ") is newer than the parser version (" + version_ + "). This might lead to undefined behavior.");
00567         }
00568         //handle file accession
00569         String accession;
00570         if (optionalAttributeAsString_(accession, attributes, s_accession))
00571         {
00572           exp_->setIdentifier(accession);
00573         }
00574         //handle file id
00575         String id;
00576         if (optionalAttributeAsString_(id, attributes, s_id))
00577         {
00578           exp_->setMetaValue("mzml_id", id);
00579         }
00580       }
00581       else if (tag == "contact")
00582       {
00583         exp_->getContacts().push_back(ContactPerson());
00584       }
00585       else if (tag == "sample")
00586       {
00587         current_id_ = attributeAsString_(attributes, s_id);
00588         String name;
00589         if (optionalAttributeAsString_(name, attributes, s_name))
00590         {
00591           samples_[current_id_].setName(name);
00592         }
00593       }
00594       else if (tag == "run")
00595       {
00596         //sample
00597         String sample_ref;
00598         if (optionalAttributeAsString_(sample_ref, attributes, s_sample_ref))
00599         {
00600           exp_->setSample(samples_[sample_ref]);
00601         }
00602         //instrument
00603         String instrument_ref = attributeAsString_(attributes, s_default_instrument_configuration_ref);
00604         exp_->setInstrument(instruments_[instrument_ref]);
00605         //start time
00606         String start_time;
00607         if (optionalAttributeAsString_(start_time, attributes, s_start_time_stamp))
00608         {
00609           exp_->setDateTime(asDateTime_(start_time));
00610         }
00611         //defaultSourceFileRef
00612         String default_source_file_ref;
00613         if (optionalAttributeAsString_(default_source_file_ref, attributes, s_default_source_file_ref))
00614         {
00615           exp_->getSourceFiles().push_back(source_files_[default_source_file_ref]);
00616         }
00617       }
00618       else if (tag == "software")
00619       {
00620         current_id_ = attributeAsString_(attributes, s_id);
00621         software_[current_id_].setVersion(attributeAsString_(attributes, s_version));
00622       }
00623       else if (tag == "dataProcessing")
00624       {
00625         current_id_ = attributeAsString_(attributes, s_id);
00626       }
00627       else if (tag == "processingMethod")
00628       {
00629         DataProcessing dp;
00630         // See ticket 452: Do NOT remove  this try/catch block until foreign
00631         // software (e.g. ProteoWizard msconvert.exe) produces valid mzML.
00632         try
00633         {
00634           dp.setSoftware(software_[attributeAsString_(attributes, s_software_ref)]);
00635         }
00636         catch (Exception::ParseError& /*e*/)
00637         {
00638           LOG_ERROR << "Warning: Parsing error, \"processingMethod\" is missing the required attribute \"softwareRef\".\n" <<
00639           "The software tool which generated this mzML should be fixed. Please notify the maintainers." << std::endl;
00640         }
00641         processing_[current_id_].push_back(dp);
00642         //The order of processing methods is currently ignored
00643       }
00644       else if (tag == "instrumentConfiguration")
00645       {
00646         current_id_ = attributeAsString_(attributes, s_id);
00647 
00648         //scan settings
00649         String scan_settings_ref;
00650         if (optionalAttributeAsString_(scan_settings_ref, attributes, s_scan_settings_ref))
00651         {
00652           warning(LOAD, "Unhandled attribute 'scanSettingsRef' in 'instrumentConfiguration' tag.");
00653         }
00654       }
00655       else if (tag == "softwareRef")
00656       {
00657         //Set the software of the instrument
00658         instruments_[current_id_].setSoftware(software_[attributeAsString_(attributes, s_ref)]);
00659       }
00660       else if (tag == "source")
00661       {
00662         instruments_[current_id_].getIonSources().push_back(IonSource());
00663         instruments_[current_id_].getIonSources().back().setOrder(attributeAsInt_(attributes, s_order));
00664       }
00665       else if (tag == "analyzer")
00666       {
00667         instruments_[current_id_].getMassAnalyzers().push_back(MassAnalyzer());
00668         instruments_[current_id_].getMassAnalyzers().back().setOrder(attributeAsInt_(attributes, s_order));
00669       }
00670       else if (tag == "detector")
00671       {
00672         instruments_[current_id_].getIonDetectors().push_back(IonDetector());
00673         instruments_[current_id_].getIonDetectors().back().setOrder(attributeAsInt_(attributes, s_order));
00674       }
00675       else if (tag == "precursor")
00676       {
00677         if (in_spectrum_list_)
00678         {
00679           //initialize
00680           spec_.getPrecursors().push_back(Precursor());
00681 
00682           //source file => meta data
00683           String source_file_ref;
00684           if (optionalAttributeAsString_(source_file_ref, attributes, s_source_file_ref))
00685           {
00686             spec_.getPrecursors().back().setMetaValue("source_file_name", source_files_[source_file_ref].getNameOfFile());
00687             spec_.getPrecursors().back().setMetaValue("source_file_path", source_files_[source_file_ref].getPathToFile());
00688           }
00689           //external spectrum id => meta data
00690           String external_spectrum_id;
00691           if (optionalAttributeAsString_(external_spectrum_id, attributes, s_external_spectrum_id))
00692           {
00693             spec_.getPrecursors().back().setMetaValue("external_spectrum_id", external_spectrum_id);
00694           }
00695           //reset selected ion count
00696           selected_ion_count_ = 0;
00697         }
00698         else
00699         {
00700           chromatogram_.setPrecursor(Precursor());
00701 
00702           String source_file_ref;
00703           if (optionalAttributeAsString_(source_file_ref, attributes, s_source_file_ref))
00704           {
00705             chromatogram_.getPrecursor().setMetaValue("source_file_name", source_files_[source_file_ref].getNameOfFile());
00706             chromatogram_.getPrecursor().setMetaValue("source_file_path", source_files_[source_file_ref].getPathToFile());
00707           }
00708 
00709           String external_spectrum_id;
00710           if (optionalAttributeAsString_(external_spectrum_id, attributes, s_external_spectrum_id))
00711           {
00712             chromatogram_.getPrecursor().setMetaValue("external_spectrum_id", external_spectrum_id);
00713           }
00714           selected_ion_count_ = 0;
00715         }
00716       }
00717       else if (tag == "product")
00718       {
00719         //initialize
00720         if (in_spectrum_list_)
00721         {
00722           spec_.getProducts().push_back(Product());
00723         }
00724         else
00725         {
00726           chromatogram_.setProduct(Product());
00727         }
00728       }
00729       else if (tag == "selectedIon")
00730       {
00731         //increase selected ion count
00732         ++selected_ion_count_;
00733       }
00734       else if (tag == "selectedIonList")
00735       {
00736         //Warn if more than one selected ion is present
00737         if (attributeAsInt_(attributes, s_count) > 1)
00738         {
00739           warning(LOAD, "OpenMS can currently handle only one selection ion per precursor! Only the first ion is loaded!");
00740         }
00741       }
00742       else if (tag == "scanWindow")
00743       {
00744         spec_.getInstrumentSettings().getScanWindows().push_back(ScanWindow());
00745       }
00746     }
00747 
00748     template <typename MapType>
00749     void MzMLHandler<MapType>::endElement(const XMLCh* const /*uri*/, const XMLCh* const /*local_name*/, const XMLCh* const qname)
00750     {
00751       static UInt scan_count = 0;
00752       static UInt chromatogram_count = 0;
00753 
00754       static const XMLCh* s_spectrum = xercesc::XMLString::transcode("spectrum");
00755       static const XMLCh* s_chromatogram = xercesc::XMLString::transcode("chromatogram");
00756       static const XMLCh* s_spectrum_list = xercesc::XMLString::transcode("spectrumList");
00757       static const XMLCh* s_chromatogram_list = xercesc::XMLString::transcode("chromatogramList");
00758       static const XMLCh* s_mzml = xercesc::XMLString::transcode("mzML");
00759 
00760       open_tags_.pop_back();
00761 
00762       if (equal_(qname, s_spectrum))
00763       {
00764         if (!skip_spectrum_)
00765         {
00766           fillData_();
00767           exp_->push_back(spec_);
00768 
00769           // catch errors stemming from confusion about elution time and scan time
00770           if (exp_->back().getRT() == -1.0 && exp_->back().metaValueExists("elution time (seconds)"))
00771           {
00772             exp_->back().setRT(exp_->back().getMetaValue("elution time (seconds)"));
00773           }
00774           /* this is too hot (could be SRM as well? -- check!):
00775                     // correct spectrum type if possible (i.e., make it more specific)
00776           if (exp_->back().getInstrumentSettings().getScanMode() == InstrumentSettings::MASSSPECTRUM)
00777           {
00778             if (exp_->back().getMSLevel() <= 1) exp_->back().getInstrumentSettings().setScanMode(InstrumentSettings::MS1SPECTRUM);
00779             else                                exp_->back().getInstrumentSettings().setScanMode(InstrumentSettings::MSNSPECTRUM);
00780           }
00781                     */
00782         }
00783         skip_spectrum_ = false;
00784         logger_.setProgress(++scan_count);
00785         data_.clear();
00786         default_array_length_ = 0;
00787       }
00788       else if (equal_(qname, s_chromatogram))
00789       {
00790         fillChromatogramData_();
00791         exp_->addChromatogram(chromatogram_);
00792         logger_.setProgress(++chromatogram_count);
00793         data_.clear();
00794         default_array_length_ = 0;
00795       }
00796       else if (equal_(qname, s_spectrum_list))
00797       {
00798         in_spectrum_list_ = false;
00799         logger_.endProgress();
00800       }
00801       else if (equal_(qname, s_chromatogram_list))
00802       {
00803         in_spectrum_list_ = false;
00804         logger_.endProgress();
00805       }
00806       else if (equal_(qname, s_mzml))
00807       {
00808         scan_count = 0;
00809         chromatogram_count = 0;
00810         ref_param_.clear();
00811         current_id_ = "";
00812         source_files_.clear();
00813         samples_.clear();
00814         software_.clear();
00815         instruments_.clear();
00816         processing_.clear();
00817       }
00818 
00819       sm_.clear();
00820     }
00821 
00822     template <typename MapType>
00823     void MzMLHandler<MapType>::fillData_()
00824     {
00825       //decode all base64 arrays
00826       for (Size i = 0; i < data_.size(); i++)
00827       {
00828         //remove whitespaces from binary data
00829         //this should not be necessary, but linebreaks inside the base64 data are unfortunately no exception
00830         data_[i].base64.removeWhitespaces();
00831 
00832         //decode data and check if the length of the decoded data matches the expected length
00833         if (data_[i].data_type == BinaryData::DT_FLOAT)
00834         {
00835           if (data_[i].precision == BinaryData::PRE_64)
00836           {
00837             decoder_.decode(data_[i].base64, Base64::BYTEORDER_LITTLEENDIAN, data_[i].floats_64, data_[i].compression);
00838             if (data_[i].size != data_[i].floats_64.size())
00839             {
00840               warning(LOAD, String("Float binary data array '") + data_[i].meta.getName() + "' of spectrum '" + spec_.getNativeID() + "' has length " + data_[i].floats_64.size() + ", but should have length " + data_[i].size + ".");
00841               data_[i].size = data_[i].floats_64.size();
00842             }
00843           }
00844           else if (data_[i].precision == BinaryData::PRE_32)
00845           {
00846             decoder_.decode(data_[i].base64, Base64::BYTEORDER_LITTLEENDIAN, data_[i].floats_32, data_[i].compression);
00847             if (data_[i].size != data_[i].floats_32.size())
00848             {
00849               warning(LOAD, String("Float binary data array '") + data_[i].meta.getName() + "' of spectrum '" + spec_.getNativeID() + "' has length " + data_[i].floats_32.size() + ", but should have length " + data_[i].size + ".");
00850               data_[i].size = data_[i].floats_32.size();
00851             }
00852           }
00853         }
00854         else if (data_[i].data_type == BinaryData::DT_INT)
00855         {
00856           if (data_[i].precision == BinaryData::PRE_64)
00857           {
00858             decoder_.decodeIntegers(data_[i].base64, Base64::BYTEORDER_LITTLEENDIAN, data_[i].ints_64, data_[i].compression);
00859             if (data_[i].size != data_[i].ints_64.size())
00860             {
00861               warning(LOAD, String("Integer binary data array '") + data_[i].meta.getName() + "' of spectrum '" + spec_.getNativeID() + "' has length " + data_[i].ints_64.size() + ", but should have length " + data_[i].size + ".");
00862               data_[i].size = data_[i].ints_64.size();
00863             }
00864           }
00865           else if (data_[i].precision == BinaryData::PRE_32)
00866           {
00867             decoder_.decodeIntegers(data_[i].base64, Base64::BYTEORDER_LITTLEENDIAN, data_[i].ints_32, data_[i].compression);
00868             if (data_[i].size != data_[i].ints_32.size())
00869             {
00870               warning(LOAD, String("Integer binary data array '") + data_[i].meta.getName() + "' of spectrum '" + spec_.getNativeID() + "' has length " + data_[i].ints_32.size() + ", but should have length " + data_[i].size + ".");
00871               data_[i].size = data_[i].ints_32.size();
00872             }
00873           }
00874         }
00875         else if (data_[i].data_type == BinaryData::DT_STRING)
00876         {
00877           decoder_.decodeStrings(data_[i].base64, data_[i].decoded_char, data_[i].compression);
00878           if (data_[i].size != data_[i].decoded_char.size())
00879           {
00880             warning(LOAD, String("String binary data array '") + data_[i].meta.getName() + "' of spectrum '" + spec_.getNativeID() + "' has length " + data_[i].decoded_char.size() + ", but should have length " + data_[i].size + ".");
00881             data_[i].size = data_[i].decoded_char.size();
00882           }
00883         }
00884       }
00885 
00886       //look up the precision and the index of the intensity and m/z array
00887       bool mz_precision_64 = true;
00888       bool int_precision_64 = true;
00889       SignedSize mz_index = -1;
00890       SignedSize int_index = -1;
00891       for (Size i = 0; i < data_.size(); i++)
00892       {
00893         if (data_[i].meta.getName() == "m/z array")
00894         {
00895           mz_index = i;
00896           mz_precision_64 = (data_[i].precision == BinaryData::PRE_64);
00897         }
00898         if (data_[i].meta.getName() == "intensity array")
00899         {
00900           int_index = i;
00901           int_precision_64 = (data_[i].precision == BinaryData::PRE_64);
00902         }
00903       }
00904 
00905       //Abort if no m/z or intensity array is present
00906       if (int_index == -1 || mz_index == -1)
00907       {
00908         //if defaultArrayLength > 0 : warn that no m/z or int arrays is present
00909         if (default_array_length_ != 0)
00910         {
00911           warning(LOAD, String("The m/z or intensity array of spectrum '") + spec_.getNativeID() + "' is missing and default_array_length_ is " + default_array_length_ + ".");
00912         }
00913         return;
00914       }
00915 
00916 
00917       // Error if intensity or m/z is encoded as int32|64 - they should be float32|64!
00918       if ((data_[mz_index].ints_32.size() > 0) || (data_[mz_index].ints_64.size() > 0))
00919       {
00920         fatalError(LOAD, "Encoding m/z array as integer is not allowed!");
00921       }
00922       if ((data_[int_index].ints_32.size() > 0) || (data_[int_index].ints_64.size() > 0))
00923       {
00924         fatalError(LOAD, "Encoding intensity array as integer is not allowed!");
00925       }
00926 
00927       // Warn if the decoded data has a different size than the the defaultArrayLength
00928       Size mz_size = mz_precision_64 ? data_[mz_index].floats_64.size() : data_[mz_index].floats_32.size();
00929       Size int_size = int_precision_64 ? data_[int_index].floats_64.size() : data_[int_index].floats_32.size();
00930       // Check if int-size and mz-size are equal
00931       if (mz_size != int_size)
00932       {
00933         fatalError(LOAD, String("The length of m/z and integer values of spectrum '") + spec_.getNativeID() + "' differ (mz-size: " + mz_size + ", int-size: " + int_size + "! Not reading spectrum!");
00934       }
00935       bool repair_array_length = false;
00936       if (default_array_length_ != mz_size)
00937       {
00938         warning(LOAD, String("The m/z array of spectrum '") + spec_.getNativeID() + "' has the size " + mz_size + ", but it should have size " + default_array_length_ + " (defaultArrayLength).");
00939         repair_array_length = true;
00940       }
00941       if (default_array_length_ != int_size)
00942       {
00943         warning(LOAD, String("The intensity array of spectrum '") + spec_.getNativeID() + "' has the size " + int_size + ", but it should have size " + default_array_length_ + " (defaultArrayLength).");
00944         repair_array_length = true;
00945       }
00946       if (repair_array_length)
00947       {
00948         default_array_length_ = int_size;
00949         warning(LOAD, String("Fixing faulty defaultArrayLength to ") + default_array_length_ + ".");
00950       }
00951 
00952       //create meta data arrays and reserve enough space for the content
00953       if (data_.size() > 2)
00954       {
00955         for (Size i = 0; i < data_.size(); i++)
00956         {
00957           if (data_[i].meta.getName() != "m/z array" && data_[i].meta.getName() != "intensity array")
00958           {
00959             if (data_[i].data_type == BinaryData::DT_FLOAT)
00960             {
00961               //create new array
00962               spec_.getFloatDataArrays().resize(spec_.getFloatDataArrays().size() + 1);
00963               //reserve space in the array
00964               spec_.getFloatDataArrays().back().reserve(data_[i].size);
00965               //copy meta info into MetaInfoDescription
00966               spec_.getFloatDataArrays().back().MetaInfoDescription::operator=(data_[i].meta);
00967             }
00968             else if (data_[i].data_type == BinaryData::DT_INT)
00969             {
00970               //create new array
00971               spec_.getIntegerDataArrays().resize(spec_.getIntegerDataArrays().size() + 1);
00972               //reserve space in the array
00973               spec_.getIntegerDataArrays().back().reserve(data_[i].size);
00974               //copy meta info into MetaInfoDescription
00975               spec_.getIntegerDataArrays().back().MetaInfoDescription::operator=(data_[i].meta);
00976             }
00977             else if (data_[i].data_type == BinaryData::DT_STRING)
00978             {
00979               //create new array
00980               spec_.getStringDataArrays().resize(spec_.getStringDataArrays().size() + 1);
00981               //reserve space in the array
00982               spec_.getStringDataArrays().back().reserve(data_[i].decoded_char.size());
00983               //copy meta info into MetaInfoDescription
00984               spec_.getStringDataArrays().back().MetaInfoDescription::operator=(data_[i].meta);
00985             }
00986           }
00987         }
00988       }
00989 
00990       // Copy meta data from m/z and intensity binary
00991       // We don't have this as a separate location => store it in spectrum
00992       for (Size i = 0; i < data_.size(); i++)
00993       {
00994         if (data_[i].meta.getName() == "m/z array" || data_[i].meta.getName() == "intensity array")
00995         {
00996           std::vector<UInt> keys;
00997           data_[i].meta.getKeys(keys);
00998           for (Size k = 0; k < keys.size(); ++k)
00999           {
01000             spec_.setMetaValue(keys[k], data_[i].meta.getMetaValue(keys[k]));
01001           }
01002         }
01003       }
01004 
01005       //add the peaks and the meta data to the container (if they pass the restrictions)
01006       spec_.reserve(default_array_length_);
01007       for (Size n = 0; n < default_array_length_; n++)
01008       {
01009         DoubleReal mz = mz_precision_64 ? data_[mz_index].floats_64[n] : data_[mz_index].floats_32[n];
01010         DoubleReal intensity = int_precision_64 ? data_[int_index].floats_64[n] : data_[int_index].floats_32[n];
01011         if ((!options_.hasMZRange() || options_.getMZRange().encloses(DPosition<1>(mz)))
01012            && (!options_.hasIntensityRange() || options_.getIntensityRange().encloses(DPosition<1>(intensity))))
01013         {
01014           //add peak
01015           PeakType tmp;
01016           tmp.setIntensity(intensity);
01017           tmp.setMZ(mz);
01018           spec_.push_back(tmp);
01019 
01020           //add meta data
01021           UInt meta_float_array_index = 0;
01022           UInt meta_int_array_index = 0;
01023           UInt meta_string_array_index = 0;
01024           for (Size i = 0; i < data_.size(); i++) //loop over all binary data arrays
01025           {
01026             if (data_[i].meta.getName() != "m/z array" && data_[i].meta.getName() != "intensity array") // is meta data array?
01027             {
01028               if (data_[i].data_type == BinaryData::DT_FLOAT)
01029               {
01030                 if (n < data_[i].size)
01031                 {
01032                   DoubleReal value = (data_[i].precision == BinaryData::PRE_64) ? data_[i].floats_64[n] : data_[i].floats_32[n];
01033                   spec_.getFloatDataArrays()[meta_float_array_index].push_back(value);
01034                 }
01035                 ++meta_float_array_index;
01036               }
01037               else if (data_[i].data_type == BinaryData::DT_INT)
01038               {
01039                 if (n < data_[i].size)
01040                 {
01041                   Int64 value = (data_[i].precision == BinaryData::PRE_64) ? data_[i].ints_64[n] : data_[i].ints_32[n];
01042                   spec_.getIntegerDataArrays()[meta_int_array_index].push_back(value);
01043                 }
01044                 ++meta_int_array_index;
01045               }
01046               else if (data_[i].data_type == BinaryData::DT_STRING)
01047               {
01048                 if (n < data_[i].decoded_char.size())
01049                 {
01050                   String value = data_[i].decoded_char[n];
01051                   spec_.getStringDataArrays()[meta_string_array_index].push_back(value);
01052                 }
01053                 ++meta_string_array_index;
01054               }
01055             }
01056           }
01057         }
01058       }
01059     }
01060 
01061     template <typename MapType>
01062     void MzMLHandler<MapType>::fillChromatogramData_()
01063     {
01064       //decode all base64 arrays
01065       for (Size i = 0; i < data_.size(); i++)
01066       {
01067         //remove whitespaces from binary data
01068         //this should not be necessary, but linebreaks inside the base64 data are unfortunately no exception
01069         data_[i].base64.removeWhitespaces();
01070 
01071         //decode data and check if the length of the decoded data matches the expected length
01072         if (data_[i].data_type == BinaryData::DT_FLOAT)
01073         {
01074           if (data_[i].precision == BinaryData::PRE_64)
01075           {
01076             decoder_.decode(data_[i].base64, Base64::BYTEORDER_LITTLEENDIAN, data_[i].floats_64, data_[i].compression);
01077             if (data_[i].size != data_[i].floats_64.size())
01078             {
01079               warning(LOAD, String("Float binary data array '") + data_[i].meta.getName() + "' of chromatogram '" + chromatogram_.getNativeID() + "' has length " + data_[i].floats_64.size() + ", but should have length " + data_[i].size + ".");
01080             }
01081           }
01082           else if (data_[i].precision == BinaryData::PRE_32)
01083           {
01084             decoder_.decode(data_[i].base64, Base64::BYTEORDER_LITTLEENDIAN, data_[i].floats_32, data_[i].compression);
01085             if (data_[i].size != data_[i].floats_32.size())
01086             {
01087               warning(LOAD, String("Float binary data array '") + data_[i].meta.getName() + "' of chromatogram '" + chromatogram_.getNativeID() + "' has length " + data_[i].floats_32.size() + ", but should have length " + data_[i].size + ".");
01088             }
01089           }
01090         }
01091         else if (data_[i].data_type == BinaryData::DT_INT)
01092         {
01093           if (data_[i].precision == BinaryData::PRE_64)
01094           {
01095             decoder_.decodeIntegers(data_[i].base64, Base64::BYTEORDER_LITTLEENDIAN, data_[i].ints_64, data_[i].compression);
01096             if (data_[i].size != data_[i].ints_64.size())
01097             {
01098               warning(LOAD, String("Integer binary data array '") + data_[i].meta.getName() + "' of chromatogram '" + chromatogram_.getNativeID() + "' has length " + data_[i].ints_64.size() + ", but should have length " + data_[i].size + ".");
01099             }
01100           }
01101           else if (data_[i].precision == BinaryData::PRE_32)
01102           {
01103             decoder_.decodeIntegers(data_[i].base64, Base64::BYTEORDER_LITTLEENDIAN, data_[i].ints_32, data_[i].compression);
01104             if (data_[i].size != data_[i].ints_32.size())
01105             {
01106               warning(LOAD, String("Integer binary data array '") + data_[i].meta.getName() + "' of chromatogram '" + chromatogram_.getNativeID() + "' has length " + data_[i].ints_32.size() + ", but should have length " + data_[i].size + ".");
01107             }
01108           }
01109         }
01110         else if (data_[i].data_type == BinaryData::DT_STRING)
01111         {
01112           decoder_.decodeStrings(data_[i].base64, data_[i].decoded_char, data_[i].compression);
01113           if (data_[i].size != data_[i].decoded_char.size())
01114           {
01115             warning(LOAD, String("String binary data array '") + data_[i].meta.getName() + "' of chromatogram '" + chromatogram_.getNativeID() + "' has length " + data_[i].decoded_char.size() + ", but should have length " + data_[i].size + ".");
01116           }
01117         }
01118       }
01119 
01120       //look up the precision and the index of the intensity and m/z array
01121       bool int_precision_64 = true;
01122       bool rt_precision_64 = true;
01123       SignedSize int_index = -1;
01124       SignedSize rt_index = -1;
01125       for (Size i = 0; i < data_.size(); i++)
01126       {
01127         if (data_[i].meta.getName() == "intensity array")
01128         {
01129           int_index = i;
01130           int_precision_64 = (data_[i].precision == BinaryData::PRE_64);
01131         }
01132         if (data_[i].meta.getName() == "time array")
01133         {
01134           rt_index = i;
01135           rt_precision_64 = (data_[i].precision == BinaryData::PRE_64);
01136         }
01137       }
01138 
01139       //Abort if no m/z or intensity array is present
01140       if (int_index == -1 || rt_index == -1)
01141       {
01142         //if defaultArrayLength > 0 : warn that no m/z or int arrays is present
01143         if (default_array_length_ != 0)
01144         {
01145           warning(LOAD, String("The m/z or intensity array of chromatogram '") + chromatogram_.getNativeID() + "' is missing and default_array_length_ is " + default_array_length_ + ".");
01146         }
01147         return;
01148       }
01149 
01150       //Warn if the decoded data has a different size than the the defaultArrayLength
01151       Size rt_size = rt_precision_64 ? data_[rt_index].floats_64.size() : data_[rt_index].floats_32.size();
01152       if (default_array_length_ != rt_size)
01153       {
01154         warning(LOAD, String("The base64-decoded rt array of chromatogram '") + chromatogram_.getNativeID() + "' has the size " + rt_size + ", but it should have size " + default_array_length_ + " (defaultArrayLength).");
01155       }
01156       Size int_size = int_precision_64 ? data_[int_index].floats_64.size() : data_[int_index].floats_32.size();
01157       if (default_array_length_ != int_size)
01158       {
01159         warning(LOAD, String("The base64-decoded intensity array of chromatogram '") + chromatogram_.getNativeID() + "' has the size " + int_size + ", but it should have size " + default_array_length_ + " (defaultArrayLength).");
01160       }
01161 
01162       //create meta data arrays and reserve enough space for the content
01163       if (data_.size() > 2)
01164       {
01165         for (Size i = 0; i < data_.size(); i++)
01166         {
01167           if (data_[i].meta.getName() != "intensity array" && data_[i].meta.getName() != "time array")
01168           {
01169             if (data_[i].data_type == BinaryData::DT_FLOAT)
01170             {
01171               //create new array
01172               chromatogram_.getFloatDataArrays().resize(chromatogram_.getFloatDataArrays().size() + 1);
01173               //reserve space in the array
01174               chromatogram_.getFloatDataArrays().back().reserve(data_[i].size);
01175               //copy meta info into MetaInfoDescription
01176               chromatogram_.getFloatDataArrays().back().MetaInfoDescription::operator=(data_[i].meta);
01177             }
01178             else if (data_[i].data_type == BinaryData::DT_INT)
01179             {
01180               //create new array
01181               chromatogram_.getIntegerDataArrays().resize(chromatogram_.getIntegerDataArrays().size() + 1);
01182               //reserve space in the array
01183               chromatogram_.getIntegerDataArrays().back().reserve(data_[i].size);
01184               //copy meta info into MetaInfoDescription
01185               chromatogram_.getIntegerDataArrays().back().MetaInfoDescription::operator=(data_[i].meta);
01186             }
01187             else if (data_[i].data_type == BinaryData::DT_STRING)
01188             {
01189               //create new array
01190               chromatogram_.getStringDataArrays().resize(chromatogram_.getStringDataArrays().size() + 1);
01191               //reserve space in the array
01192               chromatogram_.getStringDataArrays().back().reserve(data_[i].decoded_char.size());
01193               //copy meta info into MetaInfoDescription
01194               chromatogram_.getStringDataArrays().back().MetaInfoDescription::operator=(data_[i].meta);
01195             }
01196           }
01197         }
01198       }
01199 
01200       //copy meta data from time and intensity binary
01201       //We don't have this as a separate location => store it in spectrum
01202       for (Size i = 0; i < data_.size(); i++)
01203       {
01204         if (data_[i].meta.getName() == "time array" || data_[i].meta.getName() == "intensity array")
01205         {
01206           std::vector<UInt> keys;
01207           data_[i].meta.getKeys(keys);
01208           for (Size k = 0; k < keys.size(); ++k)
01209           {
01210             chromatogram_.setMetaValue(keys[k], data_[i].meta.getMetaValue(keys[k]));
01211           }
01212         }
01213       }
01214 
01215       //add the peaks and the meta data to the container (if they pass the restrictions)
01216       chromatogram_.reserve(default_array_length_);
01217       for (Size n = 0; n < default_array_length_; n++)
01218       {
01219         DoubleReal rt = rt_precision_64 ? data_[rt_index].floats_64[n] : data_[rt_index].floats_32[n];
01220         DoubleReal intensity = int_precision_64 ? data_[int_index].floats_64[n] : data_[int_index].floats_32[n];
01221         if ((!options_.hasRTRange() || options_.getRTRange().encloses(DPosition<1>(rt)))
01222            && (!options_.hasIntensityRange() || options_.getIntensityRange().encloses(DPosition<1>(intensity))))
01223         {
01224           //add peak
01225           ChromatogramPeakType tmp;
01226           tmp.setIntensity(intensity);
01227           tmp.setRT(rt);
01228           chromatogram_.push_back(tmp);
01229 
01230           //add meta data
01231           UInt meta_float_array_index = 0;
01232           UInt meta_int_array_index = 0;
01233           UInt meta_string_array_index = 0;
01234           for (Size i = 0; i < data_.size(); i++) //loop over all binary data arrays
01235           {
01236             if (data_[i].meta.getName() != "intensity array" && data_[i].meta.getName() != "time array") // is meta data array?
01237             {
01238               if (data_[i].data_type == BinaryData::DT_FLOAT)
01239               {
01240                 if (n < data_[i].size)
01241                 {
01242                   DoubleReal value = (data_[i].precision == BinaryData::PRE_64) ? data_[i].floats_64[n] : data_[i].floats_32[n];
01243                   chromatogram_.getFloatDataArrays()[meta_float_array_index].push_back(value);
01244                 }
01245                 ++meta_float_array_index;
01246               }
01247               else if (data_[i].data_type == BinaryData::DT_INT)
01248               {
01249                 if (n < data_[i].size)
01250                 {
01251                   Int64 value = (data_[i].precision == BinaryData::PRE_64) ? data_[i].ints_64[n] : data_[i].ints_32[n];
01252                   chromatogram_.getIntegerDataArrays()[meta_int_array_index].push_back(value);
01253                 }
01254                 ++meta_int_array_index;
01255               }
01256               else if (data_[i].data_type == BinaryData::DT_STRING)
01257               {
01258                 if (n < data_[i].decoded_char.size())
01259                 {
01260                   String value = data_[i].decoded_char[n];
01261                   chromatogram_.getStringDataArrays()[meta_string_array_index].push_back(value);
01262                 }
01263                 ++meta_string_array_index;
01264               }
01265             }
01266           }
01267         }
01268       }
01269     }
01270 
01271     template <typename MapType>
01272     void MzMLHandler<MapType>::handleCVParam_(const String& parent_parent_tag, const String& parent_tag, /* const String & cvref,  */ const String& accession, const String& name, const String& value, const String& unit_accession)
01273     {
01274       // the actual value stored in the CVParam
01275       // we assume for now that it is a string value, we update the type later on
01276       DataValue termValue = value;
01277 
01278       //Abort on unknown terms
01279       if (!cv_.exists(accession))
01280       {
01281         //in 'sample' several external CVs are used (Brenda, GO, ...). Do not warn then.
01282         if (parent_tag != "sample")
01283         {
01284           warning(LOAD, String("Unknown cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01285           return;
01286         }
01287       }
01288       else
01289       {
01290         const ControlledVocabulary::CVTerm& term = cv_.getTerm(accession);
01291 
01292         //obsolete CV terms
01293         if (term.obsolete)
01294         {
01295           warning(LOAD, String("Obsolete CV term '") + accession + " - " + term.name + "' used in tag '" + parent_tag + "'.");
01296         }
01297         //check if term name and parsed name match
01298         String parsed_name = name;
01299         parsed_name.trim();
01300         String correct_name = term.name;
01301         correct_name.trim();
01302         if (parsed_name != correct_name)
01303         {
01304           warning(LOAD, String("Name of CV term not correct: '") + term.id + " - " + parsed_name + "' should be '" + correct_name + "'");
01305         }
01306         if (term.obsolete)
01307         {
01308           warning(LOAD, String("Obsolete CV term '") + accession + " - " + term.name + "' used in tag '" + parent_tag + "'.");
01309         }
01310         //values used in wrong places and wrong value types
01311         if (value != "")
01312         {
01313           if (term.xref_type == ControlledVocabulary::CVTerm::NONE)
01314           {
01315             //Quality CV does not state value type :(
01316             if (!accession.hasPrefix("PATO:"))
01317             {
01318               warning(LOAD, String("The CV term '") + accession + " - " + term.name + "' used in tag '" + parent_tag + "' must not have a value. The value is '" + value + "'.");
01319             }
01320           }
01321           else
01322           {
01323             switch (term.xref_type)
01324             {
01325             //string value can be anything
01326             case ControlledVocabulary::CVTerm::XSD_STRING:
01327               break;
01328 
01329             //int value => try casting
01330             case ControlledVocabulary::CVTerm::XSD_INTEGER:
01331             case ControlledVocabulary::CVTerm::XSD_NEGATIVE_INTEGER:
01332             case ControlledVocabulary::CVTerm::XSD_POSITIVE_INTEGER:
01333             case ControlledVocabulary::CVTerm::XSD_NON_NEGATIVE_INTEGER:
01334             case ControlledVocabulary::CVTerm::XSD_NON_POSITIVE_INTEGER:
01335               try
01336               {
01337                 termValue = value.toInt();
01338               }
01339               catch (Exception::ConversionError&)
01340               {
01341                 warning(LOAD, String("The CV term '") + accession + " - " + term.name + "' used in tag '" + parent_tag + "' must have an integer value. The value is '" + value + "'.");
01342                 return;
01343               }
01344               break;
01345 
01346             //double value => try casting
01347             case ControlledVocabulary::CVTerm::XSD_DECIMAL:
01348               try
01349               {
01350                 termValue = value.toDouble();
01351               }
01352               catch (Exception::ConversionError&)
01353               {
01354                 warning(LOAD, String("The CV term '") + accession + " - " + term.name + "' used in tag '" + parent_tag + "' must have a floating-point value. The value is '" + value + "'.");
01355                 return;
01356               }
01357               break;
01358 
01359             //date string => try conversion
01360             case ControlledVocabulary::CVTerm::XSD_DATE:
01361               try
01362               {
01363                 DateTime tmp;
01364                 tmp.set(value);
01365               }
01366               catch (Exception::ParseError&)
01367               {
01368                 warning(LOAD, String("The CV term '") + accession + " - " + term.name + "' used in tag '" + parent_tag + "' must be a valid date. The value is '" + value + "'.");
01369                 return;
01370               }
01371               break;
01372 
01373             default:
01374               warning(LOAD, String("The CV term '") + accession + " - " + term.name + "' used in tag '" + parent_tag + "' has the unknown value type '" + ControlledVocabulary::CVTerm::getXRefTypeName(term.xref_type) + "'.");
01375               break;
01376             }
01377           }
01378         }
01379         //no value, although there should be a numerical value
01380         else if (term.xref_type != ControlledVocabulary::CVTerm::NONE && term.xref_type != ControlledVocabulary::CVTerm::XSD_STRING)
01381         {
01382           warning(LOAD, String("The CV term '") + accession + " - " + term.name + "' used in tag '" + parent_tag + "' should have a numerical value. The value is '" + value + "'.");
01383           return;
01384         }
01385       }
01386 
01387       if (unit_accession != "") termValue.setUnit(unit_accession);
01388 
01389       //------------------------- run ----------------------------
01390       if (parent_tag == "run")
01391       {
01392         //MS:1000857 ! run attribute
01393         if (accession == "MS:1000858") //fraction identifier
01394         {
01395           exp_->setFractionIdentifier(value);
01396         }
01397         else
01398           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01399       }
01400       //------------------------- binaryDataArray ----------------------------
01401       else if (parent_tag == "binaryDataArray")
01402       {
01403         //MS:1000518 ! binary data type
01404         if (accession == "MS:1000523") //64-bit float
01405         {
01406           data_.back().precision = BinaryData::PRE_64;
01407           data_.back().data_type = BinaryData::DT_FLOAT;
01408         }
01409         else if (accession == "MS:1000521")       //32-bit float
01410         {
01411           data_.back().precision = BinaryData::PRE_32;
01412           data_.back().data_type = BinaryData::DT_FLOAT;
01413         }
01414         else if (accession == "MS:1000519")      //32-bit integer
01415         {
01416           data_.back().precision = BinaryData::PRE_32;
01417           data_.back().data_type = BinaryData::DT_INT;
01418         }
01419         else if (accession == "MS:1000522")      //64-bit integer
01420         {
01421           data_.back().precision = BinaryData::PRE_64;
01422           data_.back().data_type = BinaryData::DT_INT;
01423         }
01424         else if (accession == "MS:1001479")
01425         {
01426           data_.back().precision = BinaryData::PRE_NONE;
01427           data_.back().data_type = BinaryData::DT_STRING;
01428         }
01429         //MS:1000513 ! binary data array
01430         else if (accession == "MS:1000786") // non-standard binary data array (with name as value)
01431         {
01432           data_.back().meta.setName(value);
01433         }
01434         else if (cv_.isChildOf(accession, "MS:1000513"))        //other array names as string
01435         {
01436           data_.back().meta.setName(cv_.getTerm(accession).name);
01437         }
01438         //MS:1000572 ! binary data compression type
01439         else if (accession == "MS:1000574") //zlib compression
01440         {
01441           data_.back().compression = true;
01442         }
01443         else if (accession == "MS:1000576")      // no compression
01444         {
01445           data_.back().compression = false;
01446         }
01447         else
01448           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01449       }
01450       //------------------------- spectrum ----------------------------
01451       else if (parent_tag == "spectrum")
01452       {
01453         //spectrum type
01454         if (accession == "MS:1000294") //mass spectrum
01455         {
01456           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::MASSSPECTRUM);
01457         }
01458         else if (accession == "MS:1000579")       //MS1 spectrum
01459         {
01460           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::MS1SPECTRUM);
01461         }
01462         else if (accession == "MS:1000580")       //MSn spectrum
01463         {
01464           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::MSNSPECTRUM);
01465         }
01466         else if (accession == "MS:1000581")       //CRM spectrum
01467         {
01468           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::CRM);
01469         }
01470         else if (accession == "MS:1000582")       //SIM spectrum
01471         {
01472           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::SIM);
01473         }
01474         else if (accession == "MS:1000583")       //SRM spectrum
01475         {
01476           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::SRM);
01477         }
01478         else if (accession == "MS:1000804")       //electromagnetic radiation spectrum
01479         {
01480           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::EMR);
01481         }
01482         else if (accession == "MS:1000805")       //emission spectrum
01483         {
01484           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::EMISSION);
01485         }
01486         else if (accession == "MS:1000806")       //absorption spectrum
01487         {
01488           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::ABSORBTION);
01489         }
01490         else if (accession == "MS:1000325")       //constant neutral gain spectrum
01491         {
01492           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::CNG);
01493         }
01494         else if (accession == "MS:1000326")       //constant neutral loss spectrum
01495         {
01496           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::CNL);
01497         }
01498         else if (accession == "MS:1000341")       //precursor ion spectrum
01499         {
01500           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::PRECURSOR);
01501         }
01502         else if (accession == "MS:1000789")       //enhanced multiply charged spectrum
01503         {
01504           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::EMC);
01505         }
01506         else if (accession == "MS:1000790")       //time-delayed fragmentation spectrum
01507         {
01508           spec_.getInstrumentSettings().setScanMode(InstrumentSettings::TDF);
01509         }
01510         //spectrum representation
01511         else if (accession == "MS:1000127") //centroid spectrum
01512         {
01513           spec_.setType(SpectrumSettings::PEAKS);
01514         }
01515         else if (accession == "MS:1000128")       //profile spectrum
01516         {
01517           spec_.setType(SpectrumSettings::RAWDATA);
01518         }
01519         else if (accession == "MS:1000525")       //spectrum representation
01520         {
01521           spec_.setType(SpectrumSettings::UNKNOWN);
01522         }
01523         //spectrum attribute
01524         else if (accession == "MS:1000511") //ms level
01525         {
01526           spec_.setMSLevel(value.toInt());
01527 
01528           if (options_.hasMSLevels() && !options_.containsMSLevel(spec_.getMSLevel()))
01529           {
01530             skip_spectrum_ = true;
01531           }
01532         }
01533         else if (accession == "MS:1000497")       //zoom scan
01534         {
01535           spec_.getInstrumentSettings().setZoomScan(true);
01536         }
01537         else if (accession == "MS:1000285")       //total ion current
01538         {
01539           //No member => meta data
01540           spec_.setMetaValue("total ion current", termValue);
01541         }
01542         else if (accession == "MS:1000504")       //base peak m/z
01543         {
01544           //No member => meta data
01545           spec_.setMetaValue("base peak m/z", termValue);
01546         }
01547         else if (accession == "MS:1000505")       //base peak intensity
01548         {
01549           //No member => meta data
01550           spec_.setMetaValue("base peak intensity", termValue);
01551         }
01552         else if (accession == "MS:1000527")       //highest observed m/z
01553         {
01554           //No member => meta data
01555           spec_.setMetaValue("highest observed m/z", termValue);
01556         }
01557         else if (accession == "MS:1000528")       //lowest observed m/z
01558         {
01559           //No member => meta data
01560           spec_.setMetaValue("lowest observed m/z", termValue);
01561         }
01562         else if (accession == "MS:1000618")       //highest observed wavelength
01563         {
01564           //No member => meta data
01565           spec_.setMetaValue("highest observed wavelength", termValue);
01566         }
01567         else if (accession == "MS:1000619")       //lowest observed wavelength
01568         {
01569           //No member => meta data
01570           spec_.setMetaValue("lowest observed wavelength", termValue);
01571         }
01572         else if (accession == "MS:1000796")       //spectrum title
01573         {
01574           //No member => meta data
01575           spec_.setMetaValue("spectrum title", termValue);
01576         }
01577         else if (accession == "MS:1000797")       //peak list scans
01578         {
01579           //No member => meta data
01580           spec_.setMetaValue("peak list scans", termValue);
01581         }
01582         else if (accession == "MS:1000798")       //peak list raw scans
01583         {
01584           //No member => meta data
01585           spec_.setMetaValue("peak list raw scans", termValue);
01586         }
01587         //scan polarity
01588         else if (accession == "MS:1000129") //negative scan
01589         {
01590           spec_.getInstrumentSettings().setPolarity(IonSource::NEGATIVE);
01591         }
01592         else if (accession == "MS:1000130")      //positive scan
01593         {
01594           spec_.getInstrumentSettings().setPolarity(IonSource::POSITIVE);
01595         }
01596         else
01597           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01598       }
01599       //------------------------- scanWindow ----------------------------
01600       else if (parent_tag == "scanWindow")
01601       {
01602         if (accession == "MS:1000501") //scan window lower limit
01603         {
01604           spec_.getInstrumentSettings().getScanWindows().back().begin = value.toDouble();
01605         }
01606         else if (accession == "MS:1000500")       //scan window upper limit
01607         {
01608           spec_.getInstrumentSettings().getScanWindows().back().end = value.toDouble();
01609         }
01610         else
01611           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01612       }
01613       //------------------------- referenceableParamGroup ----------------------------
01614       else if (parent_tag == "referenceableParamGroup")
01615       {
01616         SemanticValidator::CVTerm term;
01617         term.accession = accession;
01618         term.name = name;
01619         term.value = value;
01620         term.unit_accession = unit_accession;
01621         ref_param_[current_id_].push_back(term);
01622       }
01623       //------------------------- selectedIon ----------------------------
01624       else if (parent_tag == "selectedIon")
01625       {
01626         //parse only the first selected ion
01627         if (selected_ion_count_ > 1)
01628           return;
01629 
01630         if (accession == "MS:1000744") //selected ion m/z
01631         {
01632           //this overwrites the m/z of the isolation window, as it is probably more accurate
01633           if (in_spectrum_list_)
01634           {
01635             spec_.getPrecursors().back().setMZ(value.toDouble());
01636           }
01637           else
01638           {
01639             chromatogram_.getPrecursor().setMZ(value.toDouble());
01640           }
01641         }
01642         else if (accession == "MS:1000041")       //charge state
01643         {
01644           if (in_spectrum_list_)
01645           {
01646             spec_.getPrecursors().back().setCharge(value.toInt());
01647           }
01648           else
01649           {
01650             chromatogram_.getPrecursor().setCharge(value.toInt());
01651           }
01652         }
01653         else if (accession == "MS:1000042")       //peak intensity
01654         {
01655           if (in_spectrum_list_)
01656           {
01657             spec_.getPrecursors().back().setIntensity(value.toDouble());
01658           }
01659           else
01660           {
01661             chromatogram_.getPrecursor().setIntensity(value.toDouble());
01662           }
01663         }
01664         else if (accession == "MS:1000633")       //possible charge state
01665         {
01666           if (in_spectrum_list_)
01667           {
01668             spec_.getPrecursors().back().getPossibleChargeStates().push_back(value.toInt());
01669           }
01670           else
01671           {
01672             chromatogram_.getPrecursor().getPossibleChargeStates().push_back(value.toInt());
01673           }
01674         }
01675         else
01676           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01677       }
01678       //------------------------- activation ----------------------------
01679       else if (parent_tag == "activation")
01680       {
01681         //precursor activation attribute
01682         if (in_spectrum_list_)
01683         {
01684           if (accession == "MS:1000245") //charge stripping
01685           {
01686             //No member => meta data
01687             spec_.getPrecursors().back().setMetaValue("charge stripping", String("true"));
01688           }
01689           else if (accession == "MS:1000045")         //collision energy (ev)
01690           {
01691             //No member => meta data
01692             spec_.getPrecursors().back().setMetaValue("collision energy", termValue);
01693           }
01694           else if (accession == "MS:1000412")         //buffer gas
01695           {
01696             //No member => meta data
01697             spec_.getPrecursors().back().setMetaValue("buffer gas", termValue);
01698           }
01699           else if (accession == "MS:1000419")         //collision gas
01700           {
01701             //No member => meta data
01702             spec_.getPrecursors().back().setMetaValue("collision gas", termValue);
01703           }
01704           else if (accession == "MS:1000509")         //activation energy (ev)
01705           {
01706             spec_.getPrecursors().back().setActivationEnergy(value.toDouble());
01707           }
01708           else if (accession == "MS:1000138")         //percent collision energy
01709           {
01710             //No member => meta data
01711             spec_.getPrecursors().back().setMetaValue("percent collision energy", termValue);
01712           }
01713           else if (accession == "MS:1000869")         //collision gas pressure
01714           {
01715             //No member => meta data
01716             spec_.getPrecursors().back().setMetaValue("collision gas pressure", termValue);
01717           }
01718           //dissociation method
01719           else if (accession == "MS:1000044") //dissociation method
01720           {
01721             //nothing to do here
01722           }
01723           else if (accession == "MS:1000133")         //collision-induced dissociation
01724           {
01725             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::CID);
01726           }
01727           else if (accession == "MS:1000134")         //plasma desorption
01728           {
01729             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::PD);
01730           }
01731           else if (accession == "MS:1000135")         //post-source decay
01732           {
01733             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::PSD);
01734           }
01735           else if (accession == "MS:1000136")         //surface-induced dissociation
01736           {
01737             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::SID);
01738           }
01739           else if (accession == "MS:1000242")         //blackbody infrared radiative dissociation
01740           {
01741             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::BIRD);
01742           }
01743           else if (accession == "MS:1000250")         //electron capture dissociation
01744           {
01745             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::ECD);
01746           }
01747           else if (accession == "MS:1000262")         //infrared multiphoton dissociation
01748           {
01749             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::IMD);
01750           }
01751           else if (accession == "MS:1000282")         //sustained off-resonance irradiation
01752           {
01753             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::SORI);
01754           }
01755           else if (accession == "MS:1000422")         //high-energy collision-induced dissociation
01756           {
01757             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::HCID);
01758           }
01759           else if (accession == "MS:1000433")         //low-energy collision-induced dissociation
01760           {
01761             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::LCID);
01762           }
01763           else if (accession == "MS:1000435")         //photodissociation
01764           {
01765             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::PHD);
01766           }
01767           else if (accession == "MS:1000598")         //electron transfer dissociation
01768           {
01769             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::ETD);
01770           }
01771           else if (accession == "MS:1000599")         //pulsed q dissociation
01772           {
01773             spec_.getPrecursors().back().getActivationMethods().insert(Precursor::PQD);
01774           }
01775           else
01776             warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01777         }
01778         else
01779         {
01780           if (accession == "MS:1000245") //charge stripping
01781           {
01782             //No member => meta data
01783             chromatogram_.getPrecursor().setMetaValue("charge stripping", String("true"));
01784           }
01785           else if (accession == "MS:1000045")   //collision energy (ev)
01786           {
01787             //No member => meta data
01788             chromatogram_.getPrecursor().setMetaValue("collision energy", termValue);
01789           }
01790           else if (accession == "MS:1000412") //buffer gas
01791           {
01792             //No member => meta data
01793             chromatogram_.getPrecursor().setMetaValue("buffer gas", termValue);
01794           }
01795           else if (accession == "MS:1000419") //collision gas
01796           {
01797             //No member => meta data
01798             chromatogram_.getPrecursor().setMetaValue("collision gas", termValue);
01799           }
01800           else if (accession == "MS:1000509") //activation energy (ev)
01801           {
01802             chromatogram_.getPrecursor().setActivationEnergy(value.toDouble());
01803           }
01804           else if (accession == "MS:1000138") //percent collision energy
01805           {
01806             //No member => meta data
01807             chromatogram_.getPrecursor().setMetaValue("percent collision energy", termValue);
01808           }
01809           else if (accession == "MS:1000869") //collision gas pressure
01810           {
01811             //No member => meta data
01812             chromatogram_.getPrecursor().setMetaValue("collision gas pressure", termValue);
01813           }
01814           //dissociation method
01815           else if (accession == "MS:1000044") //dissociation method
01816           {
01817             //nothing to do here
01818           }
01819           else if (accession == "MS:1000133") //collision-induced dissociation
01820           {
01821             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::CID);
01822           }
01823           else if (accession == "MS:1000134") //plasma desorption
01824           {
01825             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::PD);
01826           }
01827           else if (accession == "MS:1000135") //post-source decay
01828           {
01829             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::PSD);
01830           }
01831           else if (accession == "MS:1000136") //surface-induced dissociation
01832           {
01833             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::SID);
01834           }
01835           else if (accession == "MS:1000242") //blackbody infrared radiative dissociation
01836           {
01837             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::BIRD);
01838           }
01839           else if (accession == "MS:1000250") //electron capture dissociation
01840           {
01841             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::ECD);
01842           }
01843           else if (accession == "MS:1000262")         //infrared multiphoton dissociation
01844           {
01845             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::IMD);
01846           }
01847           else if (accession == "MS:1000282") //sustained off-resonance irradiation
01848           {
01849             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::SORI);
01850           }
01851           else if (accession == "MS:1000422") //high-energy collision-induced dissociation
01852           {
01853             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::HCID);
01854           }
01855           else if (accession == "MS:1000433") //low-energy collision-induced dissociation
01856           {
01857             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::LCID);
01858           }
01859           else if (accession == "MS:1000435") //photodissociation
01860           {
01861             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::PHD);
01862           }
01863           else if (accession == "MS:1000598") //electron transfer dissociation
01864           {
01865             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::ETD);
01866           }
01867           else if (accession == "MS:1000599") //pulsed q dissociation
01868           {
01869             chromatogram_.getPrecursor().getActivationMethods().insert(Precursor::PQD);
01870           }
01871           else
01872             warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01873         }
01874       }
01875       //------------------------- isolationWindow ----------------------------
01876       else if (parent_tag == "isolationWindow")
01877       {
01878         if (parent_parent_tag == "precursor")
01879         {
01880           if (accession == "MS:1000827") //isolation window target m/z
01881           {
01882             if (in_spectrum_list_)
01883             {
01884               spec_.getPrecursors().back().setMZ(value.toDouble());
01885             }
01886             else
01887             {
01888               chromatogram_.getPrecursor().setMZ(value.toDouble());
01889             }
01890           }
01891           else if (accession == "MS:1000828")         //isolation window lower offset
01892           {
01893             if (in_spectrum_list_)
01894             {
01895               spec_.getPrecursors().back().setIsolationWindowLowerOffset(value.toDouble());
01896             }
01897             else
01898             {
01899               chromatogram_.getPrecursor().setIsolationWindowLowerOffset(value.toDouble());
01900             }
01901           }
01902           else if (accession == "MS:1000829")         //isolation window upper offset
01903           {
01904             if (in_spectrum_list_)
01905             {
01906               spec_.getPrecursors().back().setIsolationWindowUpperOffset(value.toDouble());
01907             }
01908             else
01909             {
01910               chromatogram_.getPrecursor().setIsolationWindowUpperOffset(value.toDouble());
01911             }
01912           }
01913           else
01914             warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01915         }
01916         else if (parent_parent_tag == "product")
01917         {
01918           if (accession == "MS:1000827") //isolation window target m/z
01919           {
01920             if (in_spectrum_list_)
01921             {
01922               spec_.getProducts().back().setMZ(value.toDouble());
01923             }
01924             else
01925             {
01926               chromatogram_.getProduct().setMZ(value.toDouble());
01927             }
01928           }
01929           else if (accession == "MS:1000829")         //isolation window upper offset
01930           {
01931             if (in_spectrum_list_)
01932             {
01933               spec_.getProducts().back().setIsolationWindowUpperOffset(value.toDouble());
01934             }
01935             else
01936             {
01937               chromatogram_.getProduct().setIsolationWindowUpperOffset(value.toDouble());
01938             }
01939           }
01940           else if (accession == "MS:1000828")         //isolation window lower offset
01941           {
01942             if (in_spectrum_list_)
01943             {
01944               spec_.getProducts().back().setIsolationWindowLowerOffset(value.toDouble());
01945             }
01946             else
01947             {
01948               chromatogram_.getProduct().setIsolationWindowLowerOffset(value.toDouble());
01949             }
01950           }
01951           else
01952             warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01953         }
01954       }
01955       //------------------------- scanList ----------------------------
01956       else if (parent_tag == "scanList")
01957       {
01958         if (cv_.isChildOf(accession, "MS:1000570")) //method of combination as string
01959         {
01960           spec_.getAcquisitionInfo().setMethodOfCombination(cv_.getTerm(accession).name);
01961         }
01962         else
01963           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
01964       }
01965       //------------------------- scan ----------------------------
01966       else if (parent_tag == "scan")
01967       {
01968         //scan attributes
01969         if (accession == "MS:1000502") //dwell time
01970         {
01971           //No member => meta data
01972           spec_.setMetaValue("dwell time", termValue);
01973         }
01974         else if (accession == "MS:1000011")      //mass resolution
01975         {
01976           //No member => meta data
01977           spec_.setMetaValue("mass resolution", termValue);
01978         }
01979         else if (accession == "MS:1000015")      //scan rate
01980         {
01981           //No member => meta data
01982           spec_.setMetaValue("scan rate", termValue);
01983         }
01984         else if (accession == "MS:1000016")      //scan start time
01985         {
01986           if (unit_accession == "UO:0000031") //minutes
01987           {
01988             spec_.setRT(60.0 * value.toDouble());
01989           }
01990           else           //seconds
01991           {
01992             spec_.setRT(value.toDouble());
01993           }
01994           if (options_.hasRTRange() && !options_.getRTRange().encloses(DPosition<1>(spec_.getRT())))
01995           {
01996             skip_spectrum_ = true;
01997           }
01998         }
01999         else if (accession == "MS:1000826")      //elution time
02000         {
02001           if (unit_accession == "UO:0000031") //minutes
02002           {
02003             spec_.setMetaValue("elution time (seconds)", 60.0 * value.toDouble());
02004           }
02005           else           //seconds
02006           {
02007             spec_.setMetaValue("elution time (seconds)", value.toDouble());
02008           }
02009         }
02010         else if (accession == "MS:1000512")      //filter string
02011         {
02012           //No member => meta data
02013           spec_.setMetaValue("filter string", termValue);
02014         }
02015         else if (accession == "MS:1000803")      //analyzer scan offset
02016         {
02017           //No member => meta data
02018           spec_.setMetaValue("analyzer scan offset", termValue);
02019         }
02020         else if (accession == "MS:1000616")      //preset scan configuration
02021         {
02022           //No member => meta data
02023           spec_.setMetaValue("preset scan configuration", termValue);
02024         }
02025         else if (accession == "MS:1000800")      //mass resolving power
02026         {
02027           //No member => meta data
02028           spec_.setMetaValue("mass resolving power", termValue);
02029         }
02030         else if (accession == "MS:1000880")      //interchannel delay
02031         {
02032           //No member => meta data
02033           spec_.setMetaValue("interchannel delay", termValue);
02034         }
02035         //scan direction
02036         else if (accession == "MS:1000092") //decreasing m/z scan
02037         {
02038           //No member => meta data
02039           spec_.setMetaValue("scan direction", String("decreasing"));
02040         }
02041         else if (accession == "MS:1000093")      //increasing m/z scan
02042         {
02043           //No member => meta data
02044           spec_.setMetaValue("scan direction", String("increasing"));
02045         }
02046         //scan law
02047         else if (accession == "MS:1000094") //scan law: exponential
02048         {
02049           //No member => meta data
02050           spec_.setMetaValue("scan law", String("exponential"));
02051         }
02052         else if (accession == "MS:1000095")      //scan law: linear
02053         {
02054           //No member => meta data
02055           spec_.setMetaValue("scan law", String("linear"));
02056         }
02057         else if (accession == "MS:1000096")      //scan law: quadratic
02058         {
02059           //No member => meta data
02060           spec_.setMetaValue("scan law", String("quadratic"));
02061         }
02062         else
02063           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02064       }
02065       //------------------------- contact ----------------------------
02066       else if (parent_tag == "contact")
02067       {
02068         if (accession == "MS:1000586") //contact name
02069         {
02070           exp_->getContacts().back().setName(value);
02071         }
02072         else if (accession == "MS:1000587")       //contact address
02073         {
02074           exp_->getContacts().back().setAddress(value);
02075         }
02076         else if (accession == "MS:1000588")       //contact URL
02077         {
02078           exp_->getContacts().back().setURL(value);
02079         }
02080         else if (accession == "MS:1000589")       //contact email
02081         {
02082           exp_->getContacts().back().setEmail(value);
02083         }
02084         else if (accession == "MS:1000590")       //contact organization
02085         {
02086           exp_->getContacts().back().setInstitution(value);
02087         }
02088         else
02089           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02090       }
02091       //------------------------- sourceFile ----------------------------
02092       else if (parent_tag == "sourceFile")
02093       {
02094         if (accession == "MS:1000569") //SHA-1 checksum
02095         {
02096           source_files_[current_id_].setChecksum(value, SourceFile::SHA1);
02097         }
02098         else if (accession == "MS:1000568")       //MD5 checksum
02099         {
02100           source_files_[current_id_].setChecksum(value, SourceFile::MD5);
02101         }
02102         else if (cv_.isChildOf(accession, "MS:1000560"))        //source file type as string
02103         {
02104           source_files_[current_id_].setFileType(cv_.getTerm(accession).name);
02105         }
02106         else if (cv_.isChildOf(accession, "MS:1000767"))        //native spectrum identifier format as string
02107         {
02108           source_files_[current_id_].setNativeIDType(cv_.getTerm(accession).name);
02109         }
02110         else
02111           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02112       }
02113       //------------------------- sample ----------------------------
02114       else if (parent_tag == "sample")
02115       {
02116         if (accession == "MS:1000004") //sample mass (gram)
02117         {
02118           samples_[current_id_].setMass(value.toDouble());
02119         }
02120         else if (accession == "MS:1000001")       //sample number
02121         {
02122           samples_[current_id_].setNumber(value);
02123         }
02124         else if (accession == "MS:1000005")       //sample volume (milliliter)
02125         {
02126           samples_[current_id_].setVolume(value.toDouble());
02127         }
02128         else if (accession == "MS:1000006")       //sample concentration (gram per liter)
02129         {
02130           samples_[current_id_].setConcentration(value.toDouble());
02131         }
02132         else if (accession == "MS:1000053")       //sample batch
02133         {
02134           //No member => meta data
02135           samples_[current_id_].setMetaValue("sample batch", termValue);
02136         }
02137         else if (accession == "MS:1000047")       //emulsion
02138         {
02139           samples_[current_id_].setState(Sample::EMULSION);
02140         }
02141         else if (accession == "MS:1000048")       //gas
02142         {
02143           samples_[current_id_].setState(Sample::GAS);
02144         }
02145         else if (accession == "MS:1000049")       //liquid
02146         {
02147           samples_[current_id_].setState(Sample::LIQUID);
02148         }
02149         else if (accession == "MS:1000050")       //solid
02150         {
02151           samples_[current_id_].setState(Sample::SOLID);
02152         }
02153         else if (accession == "MS:1000051")       //solution
02154         {
02155           samples_[current_id_].setState(Sample::SOLUTION);
02156         }
02157         else if (accession == "MS:1000052")       //suspension
02158         {
02159           samples_[current_id_].setState(Sample::SUSPENSION);
02160         }
02161         else if (accession.hasPrefix("PATO:"))         //quality of an object
02162         {
02163           //No member => meta data
02164           samples_[current_id_].setMetaValue(String(name), termValue);
02165         }
02166         else if (accession.hasPrefix("GO:"))         //cellular_component
02167         {
02168           //No member => meta data
02169           samples_[current_id_].setMetaValue("GO cellular component", String(name));
02170         }
02171         else if (accession.hasPrefix("BTO:"))         //brenda source tissue ontology
02172         {
02173           //No member => meta data
02174           samples_[current_id_].setMetaValue("brenda source tissue", String(name));
02175         }
02176         else
02177           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02178       }
02179       //------------------------- instrumentConfiguration ----------------------------
02180       else if (parent_tag == "instrumentConfiguration")
02181       {
02182         //instrument model
02183         if (accession == "MS:1000031")
02184         {
02185           //unknown instrument => notthing to do
02186         }
02187         else if (cv_.isChildOf(accession, "MS:1000031"))        //instrument name as string
02188         {
02189           instruments_[current_id_].setName(cv_.getTerm(accession).name);
02190         }
02191         //instrument attribute
02192         else if (accession == "MS:1000529") //instrument serial number
02193         {
02194           //No member => meta data
02195           instruments_[current_id_].setMetaValue("instrument serial number", termValue);
02196         }
02197         else if (accession == "MS:1000032")       //customization
02198         {
02199           instruments_[current_id_].setCustomizations(value);
02200         }
02201         else if (accession == "MS:1000236")       //transmission
02202         {
02203           //No member => metadata
02204           instruments_[current_id_].setMetaValue("transmission", termValue);
02205         }
02206         //ion optics type
02207         else if (accession == "MS:1000246") //delayed extraction
02208         {
02209           instruments_[current_id_].setIonOptics(Instrument::DELAYED_EXTRACTION);
02210         }
02211         else if (accession == "MS:1000221")       //magnetic deflection
02212         {
02213           instruments_[current_id_].setIonOptics(Instrument::MAGNETIC_DEFLECTION);
02214         }
02215         else if (accession == "MS:1000275")       //collision quadrupole
02216         {
02217           instruments_[current_id_].setIonOptics(Instrument::COLLISION_QUADRUPOLE);
02218         }
02219         else if (accession == "MS:1000281")       //selected ion flow tube
02220         {
02221           instruments_[current_id_].setIonOptics(Instrument::SELECTED_ION_FLOW_TUBE);
02222         }
02223         else if (accession == "MS:1000286")       //time lag focusing
02224         {
02225           instruments_[current_id_].setIonOptics(Instrument::TIME_LAG_FOCUSING);
02226         }
02227         else if (accession == "MS:1000300")       //reflectron
02228         {
02229           instruments_[current_id_].setIonOptics(Instrument::REFLECTRON);
02230         }
02231         else if (accession == "MS:1000307")       //einzel lens
02232         {
02233           instruments_[current_id_].setIonOptics(Instrument::EINZEL_LENS);
02234         }
02235         else if (accession == "MS:1000309")       //first stability region
02236         {
02237           instruments_[current_id_].setIonOptics(Instrument::FIRST_STABILITY_REGION);
02238         }
02239         else if (accession == "MS:1000310")       //fringing field
02240         {
02241           instruments_[current_id_].setIonOptics(Instrument::FRINGING_FIELD);
02242         }
02243         else if (accession == "MS:1000311")       //kinetic energy analyzer
02244         {
02245           instruments_[current_id_].setIonOptics(Instrument::KINETIC_ENERGY_ANALYZER);
02246         }
02247         else if (accession == "MS:1000320")       //static field
02248         {
02249           instruments_[current_id_].setIonOptics(Instrument::STATIC_FIELD);
02250         }
02251         //ion optics attribute
02252         else if (accession == "MS:1000304") //accelerating voltage
02253         {
02254           //No member => metadata
02255           instruments_[current_id_].setMetaValue("accelerating voltage", termValue);
02256         }
02257         else if (accession == "MS:1000216")       //field-free region
02258         {
02259           //No member => metadata
02260           instruments_[current_id_].setMetaValue("field-free region", String("true"));
02261         }
02262         else if (accession == "MS:1000308")       //electric field strength
02263         {
02264           //No member => metadata
02265           instruments_[current_id_].setMetaValue("electric field strength", termValue);
02266         }
02267         else if (accession == "MS:1000319")       //space charge effect
02268         {
02269           //No member => metadata
02270           instruments_[current_id_].setMetaValue("space charge effect", String("true"));
02271         }
02272         else
02273           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02274       }
02275       else if (parent_tag == "source")
02276       {
02277         //inlet type
02278         if (accession == "MS:1000055") //continuous flow fast atom bombardment
02279         {
02280           instruments_[current_id_].getIonSources().back().setInletType(IonSource::CONTINUOUSFLOWFASTATOMBOMBARDMENT);
02281         }
02282         else if (accession == "MS:1000056")       //direct inlet
02283         {
02284           instruments_[current_id_].getIonSources().back().setInletType(IonSource::DIRECT);
02285         }
02286         else if (accession == "MS:1000057")       //electrospray inlet
02287         {
02288           instruments_[current_id_].getIonSources().back().setInletType(IonSource::ELECTROSPRAYINLET);
02289         }
02290         else if (accession == "MS:1000058")       //flow injection analysis
02291         {
02292           instruments_[current_id_].getIonSources().back().setInletType(IonSource::FLOWINJECTIONANALYSIS);
02293         }
02294         else if (accession == "MS:1000059")       //inductively coupled plasma
02295         {
02296           instruments_[current_id_].getIonSources().back().setInletType(IonSource::INDUCTIVELYCOUPLEDPLASMA);
02297         }
02298         else if (accession == "MS:1000060")       //infusion
02299         {
02300           instruments_[current_id_].getIonSources().back().setInletType(IonSource::INFUSION);
02301         }
02302         else if (accession == "MS:1000061")       //jet separator
02303         {
02304           instruments_[current_id_].getIonSources().back().setInletType(IonSource::JETSEPARATOR);
02305         }
02306         else if (accession == "MS:1000062")       //membrane separator
02307         {
02308           instruments_[current_id_].getIonSources().back().setInletType(IonSource::MEMBRANESEPARATOR);
02309         }
02310         else if (accession == "MS:1000063")       //moving belt
02311         {
02312           instruments_[current_id_].getIonSources().back().setInletType(IonSource::MOVINGBELT);
02313         }
02314         else if (accession == "MS:1000064")       //moving wire
02315         {
02316           instruments_[current_id_].getIonSources().back().setInletType(IonSource::MOVINGWIRE);
02317         }
02318         else if (accession == "MS:1000065")       //open split
02319         {
02320           instruments_[current_id_].getIonSources().back().setInletType(IonSource::OPENSPLIT);
02321         }
02322         else if (accession == "MS:1000066")       //particle beam
02323         {
02324           instruments_[current_id_].getIonSources().back().setInletType(IonSource::PARTICLEBEAM);
02325         }
02326         else if (accession == "MS:1000067")       //reservoir
02327         {
02328           instruments_[current_id_].getIonSources().back().setInletType(IonSource::RESERVOIR);
02329         }
02330         else if (accession == "MS:1000068")       //septum
02331         {
02332           instruments_[current_id_].getIonSources().back().setInletType(IonSource::SEPTUM);
02333         }
02334         else if (accession == "MS:1000069")       //thermospray inlet
02335         {
02336           instruments_[current_id_].getIonSources().back().setInletType(IonSource::THERMOSPRAYINLET);
02337         }
02338         else if (accession == "MS:1000248")       //direct insertion probe
02339         {
02340           instruments_[current_id_].getIonSources().back().setInletType(IonSource::BATCH);
02341         }
02342         else if (accession == "MS:1000249")       //direct liquid introduction
02343         {
02344           instruments_[current_id_].getIonSources().back().setInletType(IonSource::CHROMATOGRAPHY);
02345         }
02346         else if (accession == "MS:1000396")       //membrane inlet
02347         {
02348           instruments_[current_id_].getIonSources().back().setInletType(IonSource::MEMBRANE);
02349         }
02350         else if (accession == "MS:1000485")       //nanospray inlet
02351         {
02352           instruments_[current_id_].getIonSources().back().setInletType(IonSource::NANOSPRAY);
02353         }
02354         //ionization type
02355         else if (accession == "MS:1000071") //chemical ionization
02356         {
02357           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::CI);
02358         }
02359         else if (accession == "MS:1000073")       //electrospray ionization
02360         {
02361           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::ESI);
02362         }
02363         else if (accession == "MS:1000074")       //fast atom bombardment ionization
02364         {
02365           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::FAB);
02366         }
02367         else if (accession == "MS:1000227")       //multiphoton ionization
02368         {
02369           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::MPI);
02370         }
02371         else if (accession == "MS:1000240")       //atmospheric pressure ionization
02372         {
02373           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::API);
02374         }
02375         else if (accession == "MS:1000247")       //desorption ionization
02376         {
02377           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::DI);
02378         }
02379         else if (accession == "MS:1000255")       //flowing afterglow
02380         {
02381           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::FA);
02382         }
02383         else if (accession == "MS:1000258")       //field ionization
02384         {
02385           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::FII);
02386         }
02387         else if (accession == "MS:1000259")       //glow discharge ionization
02388         {
02389           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::GD_MS);
02390         }
02391         else if (accession == "MS:1000271")       //Negative ion chemical ionization
02392         {
02393           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::NICI);
02394         }
02395         else if (accession == "MS:1000272")       //neutralization reionization mass spectrometry
02396         {
02397           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::NRMS);
02398         }
02399         else if (accession == "MS:1000273")       //photoionization
02400         {
02401           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::PI);
02402         }
02403         else if (accession == "MS:1000274")       //pyrolysis mass spectrometry
02404         {
02405           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::PYMS);
02406         }
02407         else if (accession == "MS:1000276")       //resonance enhanced multiphoton ionization
02408         {
02409           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::REMPI);
02410         }
02411         else if (accession == "MS:1000380")       //adiabatic ionization
02412         {
02413           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::AI);
02414         }
02415         else if (accession == "MS:1000381")       //associative ionization
02416         {
02417           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::ASI);
02418         }
02419         else if (accession == "MS:1000383")       //autodetachment
02420         {
02421           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::AD);
02422         }
02423         else if (accession == "MS:1000384")       //autoionization
02424         {
02425           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::AUI);
02426         }
02427         else if (accession == "MS:1000385")       //charge exchange ionization
02428         {
02429           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::CEI);
02430         }
02431         else if (accession == "MS:1000386")       //chemi-ionization
02432         {
02433           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::CHEMI);
02434         }
02435         else if (accession == "MS:1000388")       //dissociative ionization
02436         {
02437           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::DISSI);
02438         }
02439         else if (accession == "MS:1000389")       //electron ionization
02440         {
02441           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::EI);
02442         }
02443         else if (accession == "MS:1000395")       //liquid secondary ionization
02444         {
02445           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::LSI);
02446         }
02447         else if (accession == "MS:1000399")       //penning ionization
02448         {
02449           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::PEI);
02450         }
02451         else if (accession == "MS:1000400")       //plasma desorption ionization
02452         {
02453           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::PD);
02454         }
02455         else if (accession == "MS:1000402")       //secondary ionization
02456         {
02457           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::SI);
02458         }
02459         else if (accession == "MS:1000403")       //soft ionization
02460         {
02461           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::SOI);
02462         }
02463         else if (accession == "MS:1000404")       //spark ionization
02464         {
02465           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::SPI);
02466         }
02467         else if (accession == "MS:1000406")       //surface ionization
02468         {
02469           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::SUI);
02470         }
02471         else if (accession == "MS:1000407")       //thermal ionization
02472         {
02473           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::TI);
02474         }
02475         else if (accession == "MS:1000408")       //vertical ionization
02476         {
02477           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::VI);
02478         }
02479         else if (accession == "MS:1000446")       //fast ion bombardment
02480         {
02481           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::FIB);
02482         }
02483         else if (accession == "MS:1000070")       //atmospheric pressure chemical ionization
02484         {
02485           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::APCI);
02486         }
02487         else if (accession == "MS:1000239")       //atmospheric pressure matrix-assisted laser desorption ionization
02488         {
02489           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::AP_MALDI);
02490         }
02491         else if (accession == "MS:1000382")       //atmospheric pressure photoionization
02492         {
02493           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::APPI);
02494         }
02495         else if (accession == "MS:1000075")       //matrix-assisted laser desorption ionization
02496         {
02497           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::MALDI);
02498         }
02499         else if (accession == "MS:1000257")       //field desorption
02500         {
02501           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::FD);
02502         }
02503         else if (accession == "MS:1000387")       //desorption/ionization on silicon
02504         {
02505           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::SILI);
02506         }
02507         else if (accession == "MS:1000393")       //laser desorption ionization
02508         {
02509           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::LD);
02510         }
02511         else if (accession == "MS:1000405")       //surface-assisted laser desorption ionization
02512         {
02513           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::SALDI);
02514         }
02515         else if (accession == "MS:1000397")       //microelectrospray
02516         {
02517           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::MESI);
02518         }
02519         else if (accession == "MS:1000398")       //nanoelectrospray
02520         {
02521           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::NESI);
02522         }
02523         else if (accession == "MS:1000278")       //surface enhanced laser desorption ionization
02524         {
02525           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::SELDI);
02526         }
02527         else if (accession == "MS:1000279")       //surface enhanced neat desorption
02528         {
02529           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::SEND);
02530         }
02531         else if (accession == "MS:1000008")       //ionization type (base term)
02532         {
02533           instruments_[current_id_].getIonSources().back().setIonizationMethod(IonSource::IONMETHODNULL);
02534         }
02535         //source attribute
02536         else if (accession == "MS:1000392") //ionization efficiency
02537         {
02538           //No member => meta data
02539           instruments_[current_id_].getIonSources().back().setMetaValue("ionization efficiency", termValue);
02540         }
02541         else if (accession == "MS:1000486")       //source potential
02542         {
02543           //No member => meta data
02544           instruments_[current_id_].getIonSources().back().setMetaValue("source potential", termValue);
02545         }
02546         else if (accession == "MS:1000875")       // declustering potential
02547         {
02548           //No member => meta data
02549           instruments_[current_id_].getIonSources().back().setMetaValue("declustering potential", termValue);
02550         }
02551         else if (accession == "MS:1000876")       // cone voltage
02552         {
02553           //No member => meta data
02554           instruments_[current_id_].getIonSources().back().setMetaValue("cone voltage", termValue);
02555         }
02556         else if (accession == "MS:1000877")       // tube lens
02557         {
02558           //No member => meta data
02559           instruments_[current_id_].getIonSources().back().setMetaValue("tube lens", termValue);
02560         }
02561         //laser attribute
02562         else if (accession == "MS:1000843") // wavelength
02563         {
02564           //No member => meta data
02565           instruments_[current_id_].getIonSources().back().setMetaValue("wavelength", termValue);
02566         }
02567         else if (accession == "MS:1000844")       // focus diameter x
02568         {
02569           //No member => meta data
02570           instruments_[current_id_].getIonSources().back().setMetaValue("focus diameter x", termValue);
02571         }
02572         else if (accession == "MS:1000845")       // focus diameter y
02573         {
02574           //No member => meta data
02575           instruments_[current_id_].getIonSources().back().setMetaValue("focus diameter y", termValue);
02576         }
02577         else if (accession == "MS:1000846")       // pulse energy
02578         {
02579           //No member => meta data
02580           instruments_[current_id_].getIonSources().back().setMetaValue("pulse energy", termValue);
02581         }
02582         else if (accession == "MS:1000847")       // pulse duration
02583         {
02584           //No member => meta data
02585           instruments_[current_id_].getIonSources().back().setMetaValue("pulse duration", termValue);
02586         }
02587         else if (accession == "MS:1000848")       // attenuation
02588         {
02589           //No member => meta data
02590           instruments_[current_id_].getIonSources().back().setMetaValue("attenuation", termValue);
02591         }
02592         else if (accession == "MS:1000849")       // impact angle
02593         {
02594           //No member => meta data
02595           instruments_[current_id_].getIonSources().back().setMetaValue("impact angle", termValue);
02596         }
02597         //laser type
02598         else if (accession == "MS:1000850") // gas laser
02599         {
02600           //No member => meta data
02601           instruments_[current_id_].getIonSources().back().setMetaValue("laser type", "gas laser");
02602         }
02603         else if (accession == "MS:1000851")       // solid-state laser
02604         {
02605           //No member => meta data
02606           instruments_[current_id_].getIonSources().back().setMetaValue("laser type", "solid-state laser");
02607         }
02608         else if (accession == "MS:1000852")       // dye-laser
02609         {
02610           //No member => meta data
02611           instruments_[current_id_].getIonSources().back().setMetaValue("laser type", "dye-laser");
02612         }
02613         else if (accession == "MS:1000853")       // free electron laser
02614         {
02615           //No member => meta data
02616           instruments_[current_id_].getIonSources().back().setMetaValue("laser type", "free electron laser");
02617         }
02618         //MALDI matrix application
02619         else if (accession == "MS:1000834") // matrix solution
02620         {
02621           //No member => meta data
02622           instruments_[current_id_].getIonSources().back().setMetaValue("matrix solution", termValue);
02623         }
02624         else if (accession == "MS:1000835")       // matrix solution concentration
02625         {
02626           //No member => meta data
02627           instruments_[current_id_].getIonSources().back().setMetaValue("matrix solution concentration", termValue);
02628         }
02629         // matrix application type
02630         else if (accession == "MS:1000836") // dried dropplet
02631         {
02632           //No member => meta data
02633           instruments_[current_id_].getIonSources().back().setMetaValue("matrix application type", "dried dropplet");
02634         }
02635         else if (accession == "MS:1000837")       // printed
02636         {
02637           //No member => meta data
02638           instruments_[current_id_].getIonSources().back().setMetaValue("matrix application type", "printed");
02639         }
02640         else if (accession == "MS:1000838")       // sprayed
02641         {
02642           //No member => meta data
02643           instruments_[current_id_].getIonSources().back().setMetaValue("matrix application type", "sprayed");
02644         }
02645         else if (accession == "MS:1000839")       //  precoated plate
02646         {
02647           //No member => meta data
02648           instruments_[current_id_].getIonSources().back().setMetaValue("matrix application type", " precoated plate");
02649         }
02650         else
02651           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02652       }
02653       else if (parent_tag == "analyzer")
02654       {
02655         //mass analyzer type
02656         if (accession == "MS:1000079") //fourier transform ion cyclotron resonance mass spectrometer
02657         {
02658           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::FOURIERTRANSFORM);
02659         }
02660         else if (accession == "MS:1000080")       //magnetic sector
02661         {
02662           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::SECTOR);
02663         }
02664         else if (accession == "MS:1000081")       //quadrupole
02665         {
02666           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::QUADRUPOLE);
02667         }
02668         else if (accession == "MS:1000084")       //time-of-flight
02669         {
02670           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::TOF);
02671         }
02672         else if (accession == "MS:1000254")       //electrostatic energy analyzer
02673         {
02674           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::ESA);
02675         }
02676         else if (accession == "MS:1000264")       //ion trap
02677         {
02678           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::IT);
02679         }
02680         else if (accession == "MS:1000284")       //stored waveform inverse fourier transform
02681         {
02682           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::SWIFT);
02683         }
02684         else if (accession == "MS:1000288")       //cyclotron
02685         {
02686           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::CYCLOTRON);
02687         }
02688         else if (accession == "MS:1000484")       //orbitrap
02689         {
02690           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::ORBITRAP);
02691         }
02692         else if (accession == "MS:1000078")       //axial ejection linear ion trap
02693         {
02694           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::AXIALEJECTIONLINEARIONTRAP);
02695         }
02696         else if (accession == "MS:1000082")       //quadrupole ion trap
02697         {
02698           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::PAULIONTRAP);
02699         }
02700         else if (accession == "MS:1000083")       //radial ejection linear ion trap
02701         {
02702           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::RADIALEJECTIONLINEARIONTRAP);
02703         }
02704         else if (accession == "MS:1000291")       //linear ion trap
02705         {
02706           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::LIT);
02707         }
02708         else if (accession == "MS:1000443")       //mass analyzer type (base term)
02709         {
02710           instruments_[current_id_].getMassAnalyzers().back().setType(MassAnalyzer::ANALYZERNULL);
02711         }
02712         //mass analyzer attribute
02713         else if (accession == "MS:1000014") //accuracy (ppm)
02714         {
02715           instruments_[current_id_].getMassAnalyzers().back().setAccuracy(value.toDouble());
02716         }
02717         else if (accession == "MS:1000022")       //TOF Total Path Length (meter)
02718         {
02719           instruments_[current_id_].getMassAnalyzers().back().setTOFTotalPathLength(value.toDouble());
02720         }
02721         else if (accession == "MS:1000024")       //final MS exponent
02722         {
02723           instruments_[current_id_].getMassAnalyzers().back().setFinalMSExponent(value.toInt());
02724         }
02725         else if (accession == "MS:1000025")       //magnetic field strength (tesla)
02726         {
02727           instruments_[current_id_].getMassAnalyzers().back().setMagneticFieldStrength(value.toDouble());
02728         }
02729         else if (accession == "MS:1000105")       //reflectron off
02730         {
02731           instruments_[current_id_].getMassAnalyzers().back().setReflectronState(MassAnalyzer::OFF);
02732         }
02733         else if (accession == "MS:1000106")       //reflectron on
02734         {
02735           instruments_[current_id_].getMassAnalyzers().back().setReflectronState(MassAnalyzer::ON);
02736         }
02737         else
02738           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02739       }
02740       else if (parent_tag == "detector")
02741       {
02742         //detector type
02743         if (accession == "MS:1000107") //channeltron
02744         {
02745           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::CHANNELTRON);
02746         }
02747         else if (accession == "MS:1000110")       //daly detector
02748         {
02749           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::DALYDETECTOR);
02750         }
02751         else if (accession == "MS:1000112")       //faraday cup
02752         {
02753           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::FARADAYCUP);
02754         }
02755         else if (accession == "MS:1000114")       //microchannel plate detector
02756         {
02757           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::MICROCHANNELPLATEDETECTOR);
02758         }
02759         else if (accession == "MS:1000115")       //multi-collector
02760         {
02761           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::MULTICOLLECTOR);
02762         }
02763         else if (accession == "MS:1000116")       //photomultiplier
02764         {
02765           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::PHOTOMULTIPLIER);
02766         }
02767         else if (accession == "MS:1000253")       //electron multiplier
02768         {
02769           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::ELECTRONMULTIPLIER);
02770         }
02771         else if (accession == "MS:1000345")       //array detector
02772         {
02773           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::ARRAYDETECTOR);
02774         }
02775         else if (accession == "MS:1000346")       //conversion dynode
02776         {
02777           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::CONVERSIONDYNODE);
02778         }
02779         else if (accession == "MS:1000347")       //dynode
02780         {
02781           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::DYNODE);
02782         }
02783         else if (accession == "MS:1000348")       //focal plane collector
02784         {
02785           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::FOCALPLANECOLLECTOR);
02786         }
02787         else if (accession == "MS:1000349")       //ion-to-photon detector
02788         {
02789           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::IONTOPHOTONDETECTOR);
02790         }
02791         else if (accession == "MS:1000350")       //point collector
02792         {
02793           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::POINTCOLLECTOR);
02794         }
02795         else if (accession == "MS:1000351")       //postacceleration detector
02796         {
02797           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::POSTACCELERATIONDETECTOR);
02798         }
02799         else if (accession == "MS:1000621")       //photodiode array detector
02800         {
02801           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::PHOTODIODEARRAYDETECTOR);
02802         }
02803         else if (accession == "MS:1000624")       //inductive detector
02804         {
02805           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::INDUCTIVEDETECTOR);
02806         }
02807         else if (accession == "MS:1000108")       //conversion dynode electron multiplier
02808         {
02809           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::CONVERSIONDYNODEELECTRONMULTIPLIER);
02810         }
02811         else if (accession == "MS:1000109")       //conversion dynode photomultiplier
02812         {
02813           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::CONVERSIONDYNODEPHOTOMULTIPLIER);
02814         }
02815         else if (accession == "MS:1000111")       //electron multiplier tube
02816         {
02817           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::ELECTRONMULTIPLIERTUBE);
02818         }
02819         else if (accession == "MS:1000113")       //focal plane array
02820         {
02821           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::FOCALPLANEARRAY);
02822         }
02823         else if (accession == "MS:1000026")       //detector type (base term)
02824         {
02825           instruments_[current_id_].getIonDetectors().back().setType(IonDetector::TYPENULL);
02826         }
02827         //detector attribute
02828         else if (accession == "MS:1000028") //detector resolution
02829         {
02830           instruments_[current_id_].getIonDetectors().back().setResolution(value.toDouble());
02831         }
02832         else if (accession == "MS:1000029")       //sampling frequency
02833         {
02834           instruments_[current_id_].getIonDetectors().back().setADCSamplingFrequency(value.toDouble());
02835         }
02836         //dectector acquisition mode
02837         else if (accession == "MS:1000117") //analog-digital converter
02838         {
02839           instruments_[current_id_].getIonDetectors().back().setAcquisitionMode(IonDetector::ADC);
02840         }
02841         else if (accession == "MS:1000118")       //pulse counting
02842         {
02843           instruments_[current_id_].getIonDetectors().back().setAcquisitionMode(IonDetector::PULSECOUNTING);
02844         }
02845         else if (accession == "MS:1000119")       //time-digital converter
02846         {
02847           instruments_[current_id_].getIonDetectors().back().setAcquisitionMode(IonDetector::TDC);
02848         }
02849         else if (accession == "MS:1000120")       //transient recorder
02850         {
02851           instruments_[current_id_].getIonDetectors().back().setAcquisitionMode(IonDetector::TRANSIENTRECORDER);
02852         }
02853         else
02854           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02855       }
02856       else if (parent_tag == "processingMethod")
02857       {
02858         //data processing parameter
02859         if (accession == "MS:1000629") //low intensity threshold (ion count)
02860         {
02861           processing_[current_id_].back().setMetaValue("low_intensity_threshold", termValue);
02862         }
02863         else if (accession == "MS:1000631")       //high intensity threshold (ion count)
02864         {
02865           processing_[current_id_].back().setMetaValue("high_intensity_threshold", termValue);
02866         }
02867         else if (accession == "MS:1000787")       //inclusive low intensity threshold
02868         {
02869           processing_[current_id_].back().setMetaValue("inclusive_low_intensity_threshold", termValue);
02870         }
02871         else if (accession == "MS:1000788")       //inclusive high intensity threshold
02872         {
02873           processing_[current_id_].back().setMetaValue("inclusive_high_intensity_threshold", termValue);
02874         }
02875         else if (accession == "MS:1000747")       //completion time
02876         {
02877           processing_[current_id_].back().setCompletionTime(asDateTime_(value));
02878         }
02879         //file format conversion
02880         else if (accession == "MS:1000530") //file format conversion
02881         {
02882           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::FORMAT_CONVERSION);
02883         }
02884         else if (accession == "MS:1000544")       //Conversion to mzML
02885         {
02886           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::CONVERSION_MZML);
02887         }
02888         else if (accession == "MS:1000545")       //Conversion to mzXML
02889         {
02890           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::CONVERSION_MZXML);
02891         }
02892         else if (accession == "MS:1000546")       //Conversion to mzData
02893         {
02894           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::CONVERSION_MZDATA);
02895         }
02896         else if (accession == "MS:1000741")       //Conversion to DTA
02897         {
02898           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::CONVERSION_DTA);
02899         }
02900         //data processing action
02901         else if (accession == "MS:1000543") //data processing action
02902         {
02903           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::DATA_PROCESSING);
02904         }
02905         else if (accession == "MS:1000033")       //deisotoping
02906         {
02907           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::DEISOTOPING);
02908         }
02909         else if (accession == "MS:1000034")       //charge deconvolution
02910         {
02911           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::CHARGE_DECONVOLUTION);
02912         }
02913         else if (accession == "MS:1000035" || cv_.isChildOf(accession, "MS:1000035"))       //peak picking (or child terms, we make no difference)
02914         {
02915           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::PEAK_PICKING);
02916         }
02917         else if (accession == "MS:1000592" || cv_.isChildOf(accession, "MS:1000592"))      //smoothing (or child terms, we make no difference)
02918         {
02919           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::SMOOTHING);
02920         }
02921         else if (accession == "MS:1000778" || cv_.isChildOf(accession, "MS:1000778"))      //charge state calculation (or child terms, we make no difference)
02922         {
02923           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::CHARGE_CALCULATION);
02924         }
02925         else if (accession == "MS:1000780" || cv_.isChildOf(accession, "MS:1000780"))      //precursor recalculation (or child terms, we make no difference)
02926         {
02927           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::PRECURSOR_RECALCULATION);
02928         }
02929         else if (accession == "MS:1000593")       //baseline reduction
02930         {
02931           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::BASELINE_REDUCTION);
02932         }
02933         else if (accession == "MS:1000745")       //retention time alignment
02934         {
02935           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::ALIGNMENT);
02936         }
02937         else if (accession == "MS:1001484")       //intensity normalization
02938         {
02939           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::NORMALIZATION);
02940         }
02941         else if (accession == "MS:1001485")       //m/z calibration
02942         {
02943           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::CALIBRATION);
02944         }
02945         else if (accession == "MS:1001486" || cv_.isChildOf(accession, "MS:1001486"))      //data filtering (or child terms, we make no difference)
02946         {
02947           processing_[current_id_].back().getProcessingActions().insert(DataProcessing::FILTERING);
02948         }
02949         else
02950           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02951       }
02952       else if (parent_tag == "fileContent")
02953       {
02954         if (cv_.isChildOf(accession, "MS:1000524")) //data file content
02955         {
02956           //ignored
02957           //exp_->setMetaValue(name, termValue);
02958         }
02959         else if (cv_.isChildOf(accession, "MS:1000525")) //spectrum representation
02960         {
02961           //ignored
02962           //exp_->setMetaValue(name, termValue);
02963         }
02964         else
02965           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02966       }
02967       else if (parent_tag == "software")
02968       {
02969         if (cv_.isChildOf(accession, "MS:1000531")) //software as string
02970         {
02971           if (accession == "MS:1000799") //custom unreleased software tool => use value as name
02972           {
02973             software_[current_id_].setName(value);
02974           }
02975           else           //use name as name
02976           {
02977             software_[current_id_].setName(name);
02978           }
02979         }
02980         else
02981         {
02982           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
02983         }
02984         //~ software_[current_id_].addCVTerm(   CVTerm (accession, value, const String &cv_identifier_ref, const String &value, const Unit &unit)   ); TODO somthing like that
02985       }
02986       else if (parent_tag == "chromatogram")
02987       {
02988         if (accession == "MS:1000810")
02989         {
02990           chromatogram_.setChromatogramType(ChromatogramSettings::MASS_CHROMATOGRAM);
02991         }
02992         else if (accession == "MS:1000235")
02993         {
02994           chromatogram_.setChromatogramType(ChromatogramSettings::TOTAL_ION_CURRENT_CHROMATOGRAM);
02995         }
02996         else if (accession == "MS:1000627")
02997         {
02998           chromatogram_.setChromatogramType(ChromatogramSettings::SELECTED_ION_CURRENT_CHROMATOGRAM);
02999         }
03000         else if (accession == "MS:1000628")
03001         {
03002           chromatogram_.setChromatogramType(ChromatogramSettings::BASEPEAK_CHROMATOGRAM);
03003         }
03004         else if (accession == "MS:1001472")
03005         {
03006           chromatogram_.setChromatogramType(ChromatogramSettings::SELECTED_ION_MONITORING_CHROMATOGRAM);
03007         }
03008         else if (accession == "MS:1001473")
03009         {
03010           chromatogram_.setChromatogramType(ChromatogramSettings::SELECTED_REACTION_MONITORING_CHROMATOGRAM);
03011         }
03012         else if (accession == "MS:1001474")
03013         {
03014           chromatogram_.setChromatogramType(ChromatogramSettings::SELECTED_REACTION_MONITORING_CHROMATOGRAM);
03015         }
03016         else if (accession == "MS:1000811")
03017         {
03018           chromatogram_.setChromatogramType(ChromatogramSettings::ELECTROMAGNETIC_RADIATION_CHROMATOGRAM);
03019         }
03020         else if (accession == "MS:1000812")
03021         {
03022           chromatogram_.setChromatogramType(ChromatogramSettings::ABSORPTION_CHROMATOGRAM);
03023         }
03024         else if (accession == "MS:1000813")
03025         {
03026           chromatogram_.setChromatogramType(ChromatogramSettings::EMISSION_CHROMATOGRAM);
03027         }
03028         else if (accession == "MS:1000809")
03029         {
03030           chromatogram_.setName(value);
03031         }
03032         else
03033           warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
03034       }
03035       else if (parent_tag == "target")
03036       {
03037         //allowed but, not needed
03038       }
03039       else
03040         warning(LOAD, String("Unhandled cvParam '") + accession + "' in tag '" + parent_tag + "'.");
03041     }
03042 
03043     template <typename MapType>
03044     void MzMLHandler<MapType>::handleUserParam_(const String& parent_parent_tag, const String& parent_tag, const String& name, const String& type, const String& value)
03045     {
03046       //create a DataValue that contains the data in the right type
03047       DataValue data_value;
03048       //float type
03049       if (type == "xsd:double" || type == "xsd:float")
03050       {
03051         data_value = DataValue(value.toDouble());
03052       }
03053       //integer type
03054       else if (type == "xsd:byte" || type == "xsd:decimal" || type == "xsd:int" || type == "xsd:integer" || type == "xsd:long" || type == "xsd:negativeInteger" || type == "xsd:nonNegativeInteger" || type == "xsd:nonPositiveInteger" || type == "xsd:positiveInteger" || type == "xsd:short" || type == "xsd:unsignedByte" || type == "xsd:unsignedInt" || type == "xsd:unsignedLong" || type == "xsd:unsignedShort")
03055       {
03056         data_value = DataValue(value.toInt());
03057       }
03058       //everything else is treated as a string
03059       else
03060       {
03061         data_value = DataValue(value);
03062       }
03063 
03064       //find the right MetaInfoInterface
03065       if (parent_tag == "run")
03066       {
03067         exp_->setMetaValue(name, data_value);
03068       }
03069       else if (parent_tag == "instrumentConfiguration")
03070       {
03071         instruments_[current_id_].setMetaValue(name, data_value);
03072       }
03073       else if (parent_tag == "source")
03074       {
03075         instruments_[current_id_].getIonSources().back().setMetaValue(name, data_value);
03076       }
03077       else if (parent_tag == "analyzer")
03078       {
03079         instruments_[current_id_].getMassAnalyzers().back().setMetaValue(name, data_value);
03080       }
03081       else if (parent_tag == "detector")
03082       {
03083         instruments_[current_id_].getIonDetectors().back().setMetaValue(name, data_value);
03084       }
03085       else if (parent_tag == "sample")
03086       {
03087         samples_[current_id_].setMetaValue(name, data_value);
03088       }
03089       else if (parent_tag == "software")
03090       {
03091         software_[current_id_].setMetaValue(name, data_value);
03092       }
03093       else if (parent_tag == "contact")
03094       {
03095         exp_->getContacts().back().setMetaValue(name, data_value);
03096       }
03097       else if (parent_tag == "sourceFile")
03098       {
03099         source_files_[current_id_].setMetaValue(name, data_value);
03100       }
03101       else if (parent_tag == "binaryDataArray")
03102       {
03103         data_.back().meta.setMetaValue(name, data_value);
03104       }
03105       else if (parent_tag == "spectrum")
03106       {
03107         spec_.setMetaValue(name, data_value);
03108       }
03109       else if (parent_tag == "chromatogram")
03110       {
03111         chromatogram_.setMetaValue(name, data_value);
03112       }
03113       else if (parent_tag == "scanList")
03114       {
03115         spec_.getAcquisitionInfo().setMetaValue(name, data_value);
03116       }
03117       else if (parent_tag == "scan")
03118       {
03119         spec_.getAcquisitionInfo().back().setMetaValue(name, data_value);
03120       }
03121       else if (parent_tag == "scanWindow")
03122       {
03123         spec_.getInstrumentSettings().getScanWindows().back().setMetaValue(name, data_value);
03124       }
03125       else if (parent_tag == "isolationWindow")
03126       {
03127         //We don't have this as a separate location => store it in the precursor
03128         if (parent_parent_tag == "precursor")
03129         {
03130           if (in_spectrum_list_)
03131           {
03132             spec_.getPrecursors().back().setMetaValue(name, data_value);
03133           }
03134           else
03135           {
03136             chromatogram_.getPrecursor().setMetaValue(name, data_value);
03137           }
03138         }
03139         else if (parent_parent_tag == "product")
03140         {
03141           if (in_spectrum_list_)
03142           {
03143             spec_.getProducts().back().setMetaValue(name, data_value);
03144           }
03145           else
03146           {
03147             chromatogram_.getProduct().setMetaValue(name, data_value);
03148           }
03149         }
03150       }
03151       else if (parent_tag == "selectedIon")
03152       {
03153         //parse only the first selected ion
03154         if (selected_ion_count_ > 1)
03155           return;
03156 
03157         //We don't have this as a separate location => store it in the precursor
03158         if (in_spectrum_list_)
03159         {
03160           spec_.getPrecursors().back().setMetaValue(name, data_value);
03161         }
03162         else
03163         {
03164           chromatogram_.getPrecursor().setMetaValue(name, data_value);
03165         }
03166       }
03167       else if (parent_tag == "activation")
03168       {
03169         //We don't have this as a separate location => store it in the precursor
03170         if (in_spectrum_list_)
03171         {
03172           spec_.getPrecursors().back().setMetaValue(name, data_value);
03173         }
03174         else
03175         {
03176           chromatogram_.getPrecursor().setMetaValue(name, data_value);
03177         }
03178       }
03179       else if (parent_tag == "processingMethod")
03180       {
03181         processing_[current_id_].back().setMetaValue(name, data_value);
03182       }
03183       else if (parent_tag == "fileContent")
03184       {
03185         //exp_->setMetaValue(name, data_value);
03186       }
03187       else
03188         warning(LOAD, String("Unhandled userParam '") + name + "' in tag '" + parent_tag + "'.");
03189     }
03190 
03191     template <typename MapType>
03192     bool MzMLHandler<MapType>::validateCV_(const ControlledVocabulary::CVTerm& c, const String& path, const Internal::MzMLValidator& validator) const
03193     {
03194       SemanticValidator::CVTerm sc;
03195 
03196       sc.accession = c.id;
03197       sc.name = c.name;
03198       sc.has_unit_accession = false;
03199       sc.has_unit_name = false;
03200 
03201       return validator.SemanticValidator::locateTerm(path, sc);
03202     }
03203 
03204     template <typename MapType>
03205     String MzMLHandler<MapType>::writeCV_(const ControlledVocabulary::CVTerm& c, const DataValue& metaValue) const
03206     {
03207       String cvTerm = "<cvParam cvRef=\"" + c.id.prefix(':') + "\" accession=\"" + c.id + "\" name=\"" + c.name;
03208       if (!metaValue.isEmpty())
03209       {
03210         String stringMetaValue = (String)metaValue;
03211         stringMetaValue.substitute("\"", "&quot;");
03212         cvTerm += "\" value=\"" + stringMetaValue;
03213 
03214         if (metaValue.hasUnit())
03215         {
03216           //  unitAccession="UO:0000021" unitName="gram" unitCvRef="UO"
03217           ControlledVocabulary::CVTerm unit = cv_.getTerm(metaValue.getUnit());
03218           cvTerm += "\" unitAccession=\"" + unit.id + "\" unitName=\"" + unit.name + "\" unitCvRef=\"" + unit.id.prefix(2);
03219         }
03220       }
03221       cvTerm += "\"/>\n";
03222       return cvTerm;
03223     }
03224 
03225     template <typename MapType>
03226     void MzMLHandler<MapType>::writeUserParam_(std::ostream& os, const MetaInfoInterface& meta, UInt indent, String path, Internal::MzMLValidator& validator) const
03227     {
03228       std::vector<String> cvParams;
03229       std::vector<String> userParams;
03230 
03231       std::vector<String> keys;
03232       meta.getKeys(keys);
03233 
03234       for (std::vector<String>::iterator key = keys.begin(); key != keys.end(); ++key)
03235       {
03236         // special treatment of GO and BTO terms
03237         // <cvParam cvRef="BTO" accession="BTO:0000199" name="cardiac muscle"/>
03238 
03239         if (*key == "GO cellular component" || *key == "brenda source tissue")
03240         {
03241           // the CVTerm info is in the value
03242           const DataValue& metaValue = meta.getMetaValue(*key);
03243 
03244           if (cv_.hasTermWithName((String) metaValue))
03245           {
03246             ControlledVocabulary::CVTerm c = cv_.getTermByName((String) metaValue);
03247 
03248             // TODO: validate CV, we currently cannot do this as the relations in the BTO and GO are not captured by our CV impl
03249             cvParams.push_back(writeCV_(c, DataValue::EMPTY));
03250           }
03251         }
03252         else
03253         {
03254 
03255           bool writtenAsCVTerm = false;
03256           if (cv_.hasTermWithName(*key))
03257           {
03258             ControlledVocabulary::CVTerm c = cv_.getTermByName(*key); // in cv_ write cvparam else write userparam
03259             if (validateCV_(c, path, validator))
03260             {
03261               // write CV
03262               cvParams.push_back(writeCV_(c, meta.getMetaValue(*key)));
03263               writtenAsCVTerm = true;
03264             }
03265           }
03266 
03267           // if we could not write it as CVTerm we will store it at least as userParam
03268           if (!writtenAsCVTerm)
03269           {
03270             String userParam = "<userParam name=\"" + *key + "\" type=\"";
03271 
03272             const DataValue& d = meta.getMetaValue(*key);
03273             //determine type
03274             if (d.valueType() == DataValue::INT_VALUE)
03275             {
03276               userParam += "xsd:integer";
03277             }
03278             else if (d.valueType() == DataValue::DOUBLE_VALUE)
03279             {
03280               userParam += "xsd:double";
03281             }
03282             else         //string or lists are converted to string
03283             {
03284               userParam += "xsd:string";
03285             }
03286             String s = (String)(d);
03287             s.substitute("\"", "&quot;");
03288             userParam += "\" value=\"" + s + "\"/>" + "\n";
03289 
03290             userParams.push_back(userParam);
03291           }
03292         }
03293       }
03294 
03295       // write out all the cvParams and userParams in correct order
03296       for (std::vector<String>::iterator term = cvParams.begin(); term != cvParams.end(); ++term)
03297       {
03298         os << String(indent, '\t') << *term;
03299       }
03300 
03301       for (std::vector<String>::iterator term = userParams.begin(); term != userParams.end(); ++term)
03302       {
03303         os << String(indent, '\t') << *term;
03304       }
03305     }
03306 
03307     template <typename MapType>
03308     ControlledVocabulary::CVTerm MzMLHandler<MapType>::getChildWithName_(const String& parent_accession, const String& name) const
03309     {
03310       std::set<String> terms;
03311       cv_.getAllChildTerms(terms, parent_accession);
03312       for (std::set<String>::const_iterator it = terms.begin(); it != terms.end(); ++it)
03313       {
03314         if (cv_.getTerm(*it).name == name)
03315         {
03316           return cv_.getTerm(*it);
03317         }
03318       }
03319       return ControlledVocabulary::CVTerm();
03320     }
03321 
03322     template <typename MapType>
03323     void MzMLHandler<MapType>::writeSoftware_(std::ostream& os, const String& id, const Software& software, Internal::MzMLValidator& validator)
03324     {
03325       os << "\t\t<software id=\"" << id << "\" version=\"" << software.getVersion() << "\" >\n";
03326       ControlledVocabulary::CVTerm so_term = getChildWithName_("MS:1000531", software.getName());
03327       if (so_term.id == "MS:1000799")
03328       {
03329         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000799\" name=\"custom unreleased software tool\" value=\"\" />\n";
03330       }
03331       else if (so_term.id != "")
03332       {
03333         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"" << so_term.id << "\" name=\"" << so_term.name << "\" />\n";
03334       }
03335       else
03336       {
03337         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000799\" name=\"custom unreleased software tool\" value=\"" << software.getName() << "\" />\n";
03338       }
03339       writeUserParam_(os, software, 3, "/mzML/Software/cvParam/@accession", validator);
03340       os << "\t\t</software>\n";
03341     }
03342 
03343     template <typename MapType>
03344     void MzMLHandler<MapType>::writeSourceFile_(std::ostream& os, const String& id, const SourceFile& source_file, Internal::MzMLValidator& validator)
03345     {
03346       os << "\t\t\t<sourceFile id=\"" << id << "\" name=\"" << source_file.getNameOfFile() << "\" location=\"" << source_file.getPathToFile() << "\">\n";
03347       //checksum
03348       if (source_file.getChecksumType() == SourceFile::SHA1)
03349       {
03350         os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000569\" name=\"SHA-1\" value=\"" << source_file.getChecksum() << "\" />\n";
03351       }
03352       else if (source_file.getChecksumType() == SourceFile::MD5)
03353       {
03354         os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000568\" name=\"MD5\" value=\"" << source_file.getChecksum() << "\" />\n";
03355       }
03356       else       //FORCED
03357       {
03358         os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000569\" name=\"SHA-1\" value=\"\" />\n";
03359       }
03360       //file type
03361       ControlledVocabulary::CVTerm ft_term = getChildWithName_("MS:1000560", source_file.getFileType());
03362       if (ft_term.id != "")
03363       {
03364         os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"" << ft_term.id << "\" name=\"" << ft_term.name << "\" />\n";
03365       }
03366       else       //FORCED
03367       {
03368         os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000564\" name=\"PSI mzData file\" />\n";
03369       }
03370       //native ID format
03371       ControlledVocabulary::CVTerm id_term = getChildWithName_("MS:1000767", source_file.getNativeIDType());
03372       if (id_term.id != "")
03373       {
03374         os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"" << id_term.id << "\" name=\"" << id_term.name << "\" />\n";
03375       }
03376       else       //FORCED
03377       {
03378         os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000777\" name=\"spectrum identifier nativeID format\" />\n";
03379       }
03380       writeUserParam_(os, source_file, 4, "/mzML/fileDescription/sourceFileList/sourceFile/cvParam/@accession", validator);
03381       os << "\t\t\t</sourceFile>\n";
03382     }
03383 
03384     template <typename MapType>
03385     void MzMLHandler<MapType>::writeDataProcessing_(std::ostream& os, const String& id, const std::vector<DataProcessing>& dps, Internal::MzMLValidator& validator)
03386     {
03387       os << "\t\t<dataProcessing id=\"" << id << "\">\n";
03388 
03389       //FORCED
03390       if (dps.empty())
03391       {
03392         os << "\t\t\t<processingMethod order=\"0\" softwareRef=\"so_default\">\n";
03393         os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000544\" name=\"Conversion to mzML\" />\n";
03394         os << "\t\t\t\t<userParam name=\"warning\" type=\"xsd:string\" value=\"fictional processing method used to fulfill format requirements\" />\n";
03395         os << "\t\t\t</processingMethod>\n";
03396       }
03397 
03398       bool written = false;
03399       for (Size i = 0; i < dps.size(); ++i)
03400       {
03401         //data processing action
03402         os << "\t\t\t<processingMethod order=\"0\" softwareRef=\"so_" << id << "_pm_" << i << "\">\n";
03403         if (dps[i].getProcessingActions().count(DataProcessing::DATA_PROCESSING) == 1)
03404         {
03405           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000543\" name=\"data processing action\" />\n";
03406           written = true;
03407         }
03408         if (dps[i].getProcessingActions().count(DataProcessing::CHARGE_DECONVOLUTION) == 1)
03409         {
03410           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000034\" name=\"charge deconvolution\" />\n";
03411           written = true;
03412         }
03413         if (dps[i].getProcessingActions().count(DataProcessing::DEISOTOPING) == 1)
03414         {
03415           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000033\" name=\"deisotoping\" />\n";
03416           written = true;
03417         }
03418         if (dps[i].getProcessingActions().count(DataProcessing::SMOOTHING) == 1)
03419         {
03420           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000592\" name=\"smoothing\" />\n";
03421           written = true;
03422         }
03423         if (dps[i].getProcessingActions().count(DataProcessing::CHARGE_CALCULATION) == 1)
03424         {
03425           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000778\" name=\"charge state calculation\" />\n";
03426           written = true;
03427         }
03428         if (dps[i].getProcessingActions().count(DataProcessing::PRECURSOR_RECALCULATION) == 1)
03429         {
03430           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000780\" name=\"precursor recalculation\" />\n";
03431           written = true;
03432         }
03433         if (dps[i].getProcessingActions().count(DataProcessing::BASELINE_REDUCTION) == 1)
03434         {
03435           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000593\" name=\"baseline reduction\" />\n";
03436           written = true;
03437         }
03438         if (dps[i].getProcessingActions().count(DataProcessing::PEAK_PICKING) == 1)
03439         {
03440           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000035\" name=\"peak picking\" />\n";
03441           written = true;
03442         }
03443         if (dps[i].getProcessingActions().count(DataProcessing::ALIGNMENT) == 1)
03444         {
03445           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000745\" name=\"retention time alignment\" />\n";
03446           written = true;
03447         }
03448         if (dps[i].getProcessingActions().count(DataProcessing::CALIBRATION) == 1)
03449         {
03450           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1001485\" name=\"m/z calibration\" />\n";
03451           written = true;
03452         }
03453         if (dps[i].getProcessingActions().count(DataProcessing::NORMALIZATION) == 1)
03454         {
03455           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1001484\" name=\"intensity normalization\" />\n";
03456           written = true;
03457         }
03458         if (dps[i].getProcessingActions().count(DataProcessing::FILTERING) == 1)
03459         {
03460           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1001486\" name=\"data filtering\" />\n";
03461           written = true;
03462         }
03463         //file format conversion
03464         if (dps[i].getProcessingActions().count(DataProcessing::FORMAT_CONVERSION) == 1)
03465         {
03466           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000530\" name=\"file format conversion\" />\n";
03467           written = true;
03468         }
03469         if (dps[i].getProcessingActions().count(DataProcessing::CONVERSION_MZDATA) == 1)
03470         {
03471           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000546\" name=\"Conversion to mzData\" />\n";
03472           written = true;
03473         }
03474         if (dps[i].getProcessingActions().count(DataProcessing::CONVERSION_MZML) == 1)
03475         {
03476           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000544\" name=\"Conversion to mzML\" />\n";
03477           written = true;
03478         }
03479         if (dps[i].getProcessingActions().count(DataProcessing::CONVERSION_MZXML) == 1)
03480         {
03481           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000545\" name=\"Conversion to mzXML\" />\n";
03482           written = true;
03483         }
03484         if (dps[i].getProcessingActions().count(DataProcessing::CONVERSION_DTA) == 1)
03485         {
03486           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000741\" name=\"Conversion to dta\" />\n";
03487           written = true;
03488         }
03489         if (!written)
03490         {
03491           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000543\" name=\"data processing action\" />\n";
03492         }
03493 
03494         //data processing attribute
03495         if (dps[i].getCompletionTime().isValid())
03496         {
03497           os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000747\" name=\"completion time\" value=\"" << dps[i].getCompletionTime().toString("yyyy-MM-dd+hh:mm").toStdString() << "\" />\n";
03498         }
03499 
03500         writeUserParam_(os, dps[i], 4, "/mzML/dataProcessingList/dataProcessing/processingMethod/cvParam/@accession", validator);
03501         os << "\t\t\t</processingMethod>\n";
03502       }
03503 
03504       os << "\t\t</dataProcessing>\n";
03505     }
03506 
03507     template <typename MapType>
03508     void MzMLHandler<MapType>::writePrecursor_(std::ostream& os, const Precursor& precursor, Internal::MzMLValidator& validator)
03509     {
03510       os << "\t\t\t\t\t<precursor>\n";
03511       //--------------------------------------------------------------------------------------------
03512       //isolation window
03513       //--------------------------------------------------------------------------------------------
03514       os << "\t\t\t\t\t\t<isolationWindow>\n";
03515       os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000827\" name=\"isolation window target m/z\" value=\"" << precursor.getMZ() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
03516       os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000828\" name=\"isolation window lower offset\" value=\"" << precursor.getIsolationWindowLowerOffset() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
03517       os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000829\" name=\"isolation window upper offset\" value=\"" << precursor.getIsolationWindowUpperOffset() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
03518       os << "\t\t\t\t\t\t</isolationWindow>\n";
03519       //userParam: no extra object for it => no user parameters
03520 
03521       //--------------------------------------------------------------------------------------------
03522       //selected ion list
03523       //--------------------------------------------------------------------------------------------
03524       os << "\t\t\t\t\t\t<selectedIonList count=\"1\">\n";
03525       os << "\t\t\t\t\t\t\t<selectedIon>\n";
03526       os << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000744\" name=\"selected ion m/z\" value=\"" << precursor.getMZ() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
03527       os << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000041\" name=\"charge state\" value=\"" << precursor.getCharge() << "\" />\n";
03528       os << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000042\" name=\"peak intensity\" value=\"" << precursor.getIntensity() << "\" unitAccession=\"MS:1000132\" unitName=\"percent of base peak\" unitCvRef=\"MS\" />\n";
03529       for (Size j = 0; j < precursor.getPossibleChargeStates().size(); ++j)
03530       {
03531         os << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000633\" name=\"possible charge state\" value=\"" << precursor.getPossibleChargeStates()[j] << "\" />\n";
03532       }
03533       //userParam: no extra object for it => no user parameters
03534       os << "\t\t\t\t\t\t\t</selectedIon>\n";
03535       os << "\t\t\t\t\t\t</selectedIonList>\n";
03536 
03537       //--------------------------------------------------------------------------------------------
03538       //activation
03539       //--------------------------------------------------------------------------------------------
03540       os << "\t\t\t\t\t\t<activation>\n";
03541       if (precursor.getActivationEnergy() != 0)
03542       {
03543         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000509\" name=\"activation energy\" value=\"" << precursor.getActivationEnergy() << "\" unitAccession=\"UO:0000266\" unitName=\"electronvolt\" unitCvRef=\"UO\" />\n";
03544       }
03545       if (precursor.getActivationMethods().count(Precursor::CID) != 0)
03546       {
03547         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000133\" name=\"collision-induced dissociation\" />\n";
03548       }
03549       if (precursor.getActivationMethods().count(Precursor::PD) != 0)
03550       {
03551         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000134\" name=\"plasma desorption\" />\n";
03552       }
03553       if (precursor.getActivationMethods().count(Precursor::PSD) != 0)
03554       {
03555         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000135\" name=\"post-source decay\" />\n";
03556       }
03557       if (precursor.getActivationMethods().count(Precursor::SID) != 0)
03558       {
03559         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000136\" name=\"surface-induced dissociation\" />\n";
03560       }
03561       if (precursor.getActivationMethods().count(Precursor::BIRD) != 0)
03562       {
03563         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000242\" name=\"blackbody infrared radiative dissociation\" />\n";
03564       }
03565       if (precursor.getActivationMethods().count(Precursor::ECD) != 0)
03566       {
03567         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000250\" name=\"electron capture dissociation\" />\n";
03568       }
03569       if (precursor.getActivationMethods().count(Precursor::IMD) != 0)
03570       {
03571         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000262\" name=\"infrared multiphoton dissociation\" />\n";
03572       }
03573       if (precursor.getActivationMethods().count(Precursor::SORI) != 0)
03574       {
03575         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000282\" name=\"sustained off-resonance irradiation\" />\n";
03576       }
03577       if (precursor.getActivationMethods().count(Precursor::HCID) != 0)
03578       {
03579         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000422\" name=\"high-energy collision-induced dissociation\" />\n";
03580       }
03581       if (precursor.getActivationMethods().count(Precursor::LCID) != 0)
03582       {
03583         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000433\" name=\"low-energy collision-induced dissociation\" />\n";
03584       }
03585       if (precursor.getActivationMethods().count(Precursor::PHD) != 0)
03586       {
03587         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000435\" name=\"photodissociation\" />\n";
03588       }
03589       if (precursor.getActivationMethods().count(Precursor::ETD) != 0)
03590       {
03591         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000598\" name=\"electron transfer dissociation\" />\n";
03592       }
03593       if (precursor.getActivationMethods().count(Precursor::PQD) != 0)
03594       {
03595         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000599\" name=\"pulsed q dissociation\" />\n";
03596       }
03597       if (precursor.getActivationMethods().empty())
03598       {
03599         os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000044\" name=\"dissociation method\" />\n";
03600       }
03601       //as "precursor" has no own user param its userParam is stored here
03602       writeUserParam_(os, precursor, 6, "/mzML/run/spectrumList/spectrum/precursorList/precursor/activation/cvParam/@accession", validator);
03603       os << "\t\t\t\t\t\t</activation>\n";
03604       os << "\t\t\t\t\t</precursor>\n";
03605 
03606     }
03607 
03608     template <typename MapType>
03609     void MzMLHandler<MapType>::writeProduct_(std::ostream& os, const Product& product, Internal::MzMLValidator& validator)
03610     {
03611       os << "\t\t\t\t\t<product>\n";
03612       os << "\t\t\t\t\t\t<isolationWindow>\n";
03613       os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000827\" name=\"isolation window target m/z\" value=\"" << product.getMZ() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
03614       os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000828\" name=\"isolation window lower offset\" value=\"" << product.getIsolationWindowLowerOffset() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
03615       os << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000829\" name=\"isolation window upper offset\" value=\"" << product.getIsolationWindowUpperOffset() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
03616       writeUserParam_(os, product, 7, "/mzML/run/spectrumList/spectrum/productList/product/isolationWindow/cvParam/@accession", validator);
03617       os << "\t\t\t\t\t\t</isolationWindow>\n";
03618       os << "\t\t\t\t\t</product>\n";
03619     }
03620 
03621     template <typename MapType>
03622     void MzMLHandler<MapType>::writeTo(std::ostream& os)
03623     {
03624       const MapType& exp = *(cexp_);
03625       logger_.startProgress(0, exp.size() + exp.getChromatograms().size(), "storing mzML file");
03626       int progress = 0;
03627       Internal::MzMLValidator validator(mapping_, cv_);
03628 
03629       os << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
03630          << "<mzML xmlns=\"http://psi.hupo.org/ms/mzml\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://psi.hupo.org/ms/mzml http://psidev.info/files/ms/mzML/xsd/mzML1.1.0.xsd\" accession=\"" << exp.getIdentifier() << "\" version=\"" << version_ << "\">\n";
03631       //--------------------------------------------------------------------------------------------
03632       // CV list
03633       //--------------------------------------------------------------------------------------------
03634       os << "\t<cvList count=\"2\">\n"
03635          << "\t\t<cv id=\"MS\" fullName=\"Proteomics Standards Initiative Mass Spectrometry Ontology\" URI=\"http://psidev.cvs.sourceforge.net/*checkout*/psidev/psi/psi-ms/mzML/controlledVocabulary/psi-ms.obo\"/>\n"
03636          << "\t\t<cv id=\"UO\" fullName=\"Unit Ontology\" URI=\"http://obo.cvs.sourceforge.net/obo/obo/ontology/phenotype/unit.obo\"/>\n"
03637          << "\t\t<cv id=\"BTO\" fullName=\"BrendaTissue545\" version=\"unknown\" URI=\"http://www.brenda-enzymes.info/ontology/tissue/tree/update/update_files/BrendaTissueOBO\"/>\n"
03638          << "\t\t<cv id=\"GO\" fullName=\"Gene Ontology - Slim Versions\" version=\"unknown\" URI=\"http://www.geneontology.org/GO_slims/goslim_goa.obo\"/>\n"
03639          << "\t\t<cv id=\"PATO\" fullName=\"Quality ontology\" version=\"unknown\" URI=\"http://obo.cvs.sourceforge.net/*checkout*/obo/obo/ontology/phenotype/quality.obo\"/>\n"
03640          << "\t</cvList>\n";
03641       //--------------------------------------------------------------------------------------------
03642       // file content
03643       //--------------------------------------------------------------------------------------------
03644       os << "\t<fileDescription>\n";
03645       os << "\t\t<fileContent>\n";
03646       Map<InstrumentSettings::ScanMode, UInt> file_content;
03647       for (Size i = 0; i < exp.size(); ++i)
03648       {
03649         ++file_content[exp[i].getInstrumentSettings().getScanMode()];
03650       }
03651       if (file_content.has(InstrumentSettings::MASSSPECTRUM))
03652       {
03653         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000294\" name=\"mass spectrum\" />\n";
03654       }
03655       if (file_content.has(InstrumentSettings::MS1SPECTRUM))
03656       {
03657         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000579\" name=\"MS1 spectrum\" />\n";
03658       }
03659       if (file_content.has(InstrumentSettings::MSNSPECTRUM))
03660       {
03661         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000580\" name=\"MSn spectrum\" />\n";
03662       }
03663       if (file_content.has(InstrumentSettings::SIM))
03664       {
03665         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000582\" name=\"SIM spectrum\" />\n";
03666       }
03667       if (file_content.has(InstrumentSettings::SRM))
03668       {
03669         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000583\" name=\"SRM spectrum\" />\n";
03670       }
03671       if (file_content.has(InstrumentSettings::CRM))
03672       {
03673         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000581\" name=\"CRM spectrum\" />\n";
03674       }
03675       if (file_content.has(InstrumentSettings::PRECURSOR))
03676       {
03677         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000341\" name=\"precursor ion spectrum\" />\n";
03678       }
03679       if (file_content.has(InstrumentSettings::CNG))
03680       {
03681         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000325\" name=\"constant neutral gain spectrum\" />\n";
03682       }
03683       if (file_content.has(InstrumentSettings::CNL))
03684       {
03685         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000326\" name=\"constant neutral loss spectrum\" />\n";
03686       }
03687       if (file_content.has(InstrumentSettings::EMR))
03688       {
03689         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000804\" name=\"electromagnetic radiation spectrum\" />\n";
03690       }
03691       if (file_content.has(InstrumentSettings::EMISSION))
03692       {
03693         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000805\" name=\"emission spectrum\" />\n";
03694       }
03695       if (file_content.has(InstrumentSettings::ABSORBTION))
03696       {
03697         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000806\" name=\"absorption spectrum\" />\n";
03698       }
03699       if (file_content.has(InstrumentSettings::EMC))
03700       {
03701         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000789\" name=\"enhanced multiply charged spectrum\" />\n";
03702       }
03703       if (file_content.has(InstrumentSettings::TDF))
03704       {
03705         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000789\" name=\"time-delayed fragmentation spectrum\" />\n";
03706       }
03707       if (file_content.has(InstrumentSettings::UNKNOWN) || file_content.empty())
03708       {
03709         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000294\" name=\"mass spectrum\" />\n";
03710       }
03711       // writeUserParam_(os, exp, 3, "/mzML/fileDescription/fileContent/cvParam/@accession", validator);
03712       os << "\t\t</fileContent>\n";
03713       //--------------------------------------------------------------------------------------------
03714       // source file list
03715       //--------------------------------------------------------------------------------------------
03716       //find out how many spectra source files need to be written
03717       UInt sf_sp_count = 0;
03718       for (Size i = 0; i < exp.size(); ++i)
03719       {
03720         if (exp[i].getSourceFile() != SourceFile())
03721           ++sf_sp_count;
03722       }
03723       if (exp.getSourceFiles().size() > 0 || sf_sp_count > 0)
03724       {
03725         os << "\t\t<sourceFileList count=\"" << exp.getSourceFiles().size() + sf_sp_count << "\">\n";
03726         //write source file of run
03727         if (exp.getSourceFiles().size() > 0)
03728         {
03729           writeSourceFile_(os, String("sf_ru_0"), exp.getSourceFiles()[0], validator);
03730         }
03731         if (exp.getSourceFiles().size() > 1)
03732         {
03733           warning(STORE, "The MzML format can store only one source file per run. Only the first one is stored!");
03734         }
03735         //write source files of spectra
03736         for (Size i = 0; i < exp.size(); ++i)
03737         {
03738           if (exp[i].getSourceFile() != SourceFile())
03739           {
03740             writeSourceFile_(os, String("sf_sp_") + i, exp[i].getSourceFile(), validator);
03741           }
03742         }
03743         os << "\t\t</sourceFileList>\n";
03744       }
03745       //--------------------------------------------------------------------------------------------
03746       // contacts
03747       //--------------------------------------------------------------------------------------------
03748       for (Size i = 0; i < exp.getContacts().size(); ++i)
03749       {
03750         const ContactPerson& cp = exp.getContacts()[i];
03751         os << "\t\t<contact>\n";
03752         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000586\" name=\"contact name\" value=\"" << cp.getLastName() << ", " << cp.getFirstName() << "\" />\n";
03753         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000590\" name=\"contact organization\" value=\"" << cp.getInstitution() << "\" />\n";
03754 
03755         if (cp.getAddress() != "")
03756         {
03757           os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000587\" name=\"contact address\" value=\"" << cp.getAddress() << "\" />\n";
03758         }
03759         if (cp.getURL() != "")
03760         {
03761           os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000588\" name=\"contact URL\" value=\"" << cp.getURL() << "\" />\n";
03762         }
03763         if (cp.getEmail() != "")
03764         {
03765           os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000589\" name=\"contact email\" value=\"" << cp.getEmail() << "\" />\n";
03766         }
03767         if (cp.getContactInfo() != "")
03768         {
03769           os << "\t\t\t<userParam name=\"contact_info\" type=\"xsd:string\" value=\"" << cp.getContactInfo() << "\" />\n";
03770         }
03771         writeUserParam_(os, cp, 3, "/mzML/fileDescription/contact/cvParam/@accession", validator);
03772         os << "\t\t</contact>\n";
03773       }
03774       os << "\t</fileDescription>\n";
03775       //--------------------------------------------------------------------------------------------
03776       // sample
03777       //--------------------------------------------------------------------------------------------
03778       const Sample& sa = exp.getSample();
03779       os << "\t<sampleList count=\"1\">\n";
03780       os << "\t\t<sample id=\"sa_0\" name=\"" << sa.getName() << "\">\n";
03781       if (sa.getNumber() != "")
03782       {
03783         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000001\" name=\"sample number\" value=\"" << sa.getNumber() << "\" />\n";
03784       }
03785       os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000004\" name=\"sample mass\" value=\"" << sa.getMass() << "\" unitAccession=\"UO:0000021\" unitName=\"gram\" unitCvRef=\"UO\" />\n";
03786       os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000005\" name=\"sample volume\" value=\"" << sa.getVolume() << "\" unitAccession=\"UO:0000098\" unitName=\"milliliter\" unitCvRef=\"UO\" />\n";
03787       os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000006\" name=\"sample concentration\" value=\"" << sa.getConcentration() << "\" unitAccession=\"UO:0000175\" unitName=\"gram per liter\" unitCvRef=\"UO\" />\n";
03788       if (sa.getState() == Sample::EMULSION)
03789       {
03790         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000047\" name=\"emulsion\" />\n";
03791       }
03792       else if (sa.getState() == Sample::GAS)
03793       {
03794         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000048\" name=\"gas\" />\n";
03795       }
03796       else if (sa.getState() == Sample::LIQUID)
03797       {
03798         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000049\" name=\"liquid\" />\n";
03799       }
03800       else if (sa.getState() == Sample::SOLID)
03801       {
03802         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000050\" name=\"solid\" />\n";
03803       }
03804       else if (sa.getState() == Sample::SOLUTION)
03805       {
03806         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000051\" name=\"solution\" />\n";
03807       }
03808       else if (sa.getState() == Sample::SUSPENSION)
03809       {
03810         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000052\" name=\"suspension\" />\n";
03811       }
03812       if (sa.getComment() != "")
03813       {
03814         os << "\t\t\t<userParam name=\"comment\" type=\"xsd:string\" value=\"" << sa.getComment() << "\" />\n";
03815       }
03816       writeUserParam_(os, sa, 3, "/mzML/sampleList/sample/cvParam/@accession", validator);
03817       os << "\t\t</sample>\n";
03818       os << "\t</sampleList>\n";
03819 
03820       //--------------------------------------------------------------------------------------------
03821       // software
03822       //--------------------------------------------------------------------------------------------
03823 
03824       // create a list of all different data processings
03825       std::vector<std::vector<DataProcessing> > dps;
03826       Size num_software(2); // instrument software is always written
03827       for (Size s = 0; s < exp.size(); ++s)
03828       {
03829         if (find(dps.begin(), dps.end(), exp[s].getDataProcessing()) == dps.end())
03830         {
03831           dps.push_back(exp[s].getDataProcessing());
03832           num_software += exp[s].getDataProcessing().size();
03833         }
03834       }
03835       for (Size s = 0; s < exp.getChromatograms().size(); ++s)
03836       {
03837         if (find(dps.begin(), dps.end(), exp.getChromatograms()[s].getDataProcessing()) == dps.end())
03838         {
03839           dps.push_back(exp.getChromatograms()[s].getDataProcessing());
03840           num_software += exp.getChromatograms()[s].getDataProcessing().size();
03841         }
03842       }
03843 
03844       // count binary data array software
03845       Size num_bi_software(0);
03846 
03847       for (Size s = 0; s < exp.size(); ++s)
03848       {
03849         for (Size m = 0; m < exp[s].getFloatDataArrays().size(); ++m)
03850         {
03851           for (Size i = 0; i < exp[s].getFloatDataArrays()[m].getDataProcessing().size(); ++i)
03852           {
03853             ++num_bi_software;
03854           }
03855         }
03856       }
03857 
03858       os << "\t<softwareList count=\"" << num_software + num_bi_software << "\">\n";
03859       //write instrument software
03860       writeSoftware_(os, "so_in_0", exp.getInstrument().getSoftware(), validator);
03861 
03862       //write fallback software
03863       writeSoftware_(os, "so_default", Software(), validator);
03864 
03865       // write the software of the dps
03866       for (Size s1 = 0; s1 != dps.size(); ++s1)
03867       {
03868         for (Size s2 = 0; s2 != dps[s1].size(); ++s2)
03869         {
03870           writeSoftware_(os, String("so_dp_sp_") + s1 + "_pm_" + s2, dps[s1][s2].getSoftware(), validator);
03871         }
03872       }
03873 
03874       //write data processing (for each binary data array)
03875       for (Size s = 0; s < exp.size(); ++s)
03876       {
03877         for (Size m = 0; m < exp[s].getFloatDataArrays().size(); ++m)
03878         {
03879           for (Size i = 0; i < exp[s].getFloatDataArrays()[m].getDataProcessing().size(); ++i)
03880           {
03881             writeSoftware_(os, String("so_dp_sp_") + s + "_bi_" + m + "_pm_" + i, exp[s].getFloatDataArrays()[m].getDataProcessing()[i].getSoftware(), validator);
03882           }
03883         }
03884       }
03885       os << "\t</softwareList>\n";
03886 
03887       //--------------------------------------------------------------------------------------------
03888       // instrument configuration (enclosing ion source, mass analyzer and detector)
03889       //--------------------------------------------------------------------------------------------
03890       const Instrument& in = exp.getInstrument();
03891       os << "\t<instrumentConfigurationList count=\"1\">\n";
03892       os << "\t\t<instrumentConfiguration id=\"ic_0\">\n";
03893       ControlledVocabulary::CVTerm in_term = getChildWithName_("MS:1000031", in.getName());
03894       if (in_term.id != "")
03895       {
03896         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"" << in_term.id << "\" name=\"" << in_term.name << "\" />\n";
03897       }
03898       else
03899       {
03900         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000031\" name=\"instrument model\" />\n";
03901       }
03902 
03903       if (in.getCustomizations() != "")
03904       {
03905         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000032\" name=\"customization\" value=\"" << in.getCustomizations() << "\" />\n";
03906       }
03907 
03908       //ion optics
03909       if (in.getIonOptics() == Instrument::MAGNETIC_DEFLECTION)
03910       {
03911         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000221\" name=\"magnetic deflection\" />\n";
03912       }
03913       else if (in.getIonOptics() == Instrument::DELAYED_EXTRACTION)
03914       {
03915         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000246\" name=\"delayed extraction\" />\n";
03916       }
03917       else if (in.getIonOptics() == Instrument::COLLISION_QUADRUPOLE)
03918       {
03919         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000275\" name=\"collision quadrupole\" />\n";
03920       }
03921       else if (in.getIonOptics() == Instrument::SELECTED_ION_FLOW_TUBE)
03922       {
03923         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000281\" name=\"selected ion flow tube\" />\n";
03924       }
03925       else if (in.getIonOptics() == Instrument::TIME_LAG_FOCUSING)
03926       {
03927         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000286\" name=\"time lag focusing\" />\n";
03928       }
03929       else if (in.getIonOptics() == Instrument::REFLECTRON)
03930       {
03931         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000300\" name=\"reflectron\" />\n";
03932       }
03933       else if (in.getIonOptics() == Instrument::EINZEL_LENS)
03934       {
03935         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000307\" name=\"einzel lens\" />\n";
03936       }
03937       else if (in.getIonOptics() == Instrument::FIRST_STABILITY_REGION)
03938       {
03939         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000309\" name=\"first stability region\" />\n";
03940       }
03941       else if (in.getIonOptics() == Instrument::FRINGING_FIELD)
03942       {
03943         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000310\" name=\"fringing field\" />\n";
03944       }
03945       else if (in.getIonOptics() == Instrument::KINETIC_ENERGY_ANALYZER)
03946       {
03947         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000311\" name=\"kinetic energy analyzer\" />\n";
03948       }
03949       else if (in.getIonOptics() == Instrument::STATIC_FIELD)
03950       {
03951         os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000320\" name=\"static field\" />\n";
03952       }
03953 
03954       writeUserParam_(os, in, 3, "/mzML/instrumentConfigurationList/instrumentConfiguration/cvParam/@accession", validator);
03955       Size component_count = in.getIonSources().size() + in.getMassAnalyzers().size() + in.getIonDetectors().size();
03956       if (component_count != 0)
03957       {
03958         os << "\t\t\t<componentList count=\"" << (std::max)((Size)3, component_count) << "\">\n";
03959         //--------------------------------------------------------------------------------------------
03960         // ion source
03961         //--------------------------------------------------------------------------------------------
03962         for (Size i = 0; i < in.getIonSources().size(); ++i)
03963         {
03964           const IonSource& so = in.getIonSources()[i];
03965           os << "\t\t\t\t<source order=\"" << so.getOrder() << "\">\n";
03966 
03967           if (so.getInletType() == IonSource::CONTINUOUSFLOWFASTATOMBOMBARDMENT)
03968           {
03969             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000055\" name=\"continuous flow fast atom bombardment\" />\n";
03970           }
03971           else if (so.getInletType() == IonSource::DIRECT)
03972           {
03973             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000056\" name=\"direct inlet\" />\n";
03974           }
03975           else if (so.getInletType() == IonSource::ELECTROSPRAYINLET)
03976           {
03977             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000057\" name=\"electrospray inlet\" />\n";
03978           }
03979           else if (so.getInletType() == IonSource::FLOWINJECTIONANALYSIS)
03980           {
03981             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000058\" name=\"flow injection analysis\" />\n";
03982           }
03983           else if (so.getInletType() == IonSource::INDUCTIVELYCOUPLEDPLASMA)
03984           {
03985             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000059\" name=\"inductively coupled plasma\" />\n";
03986           }
03987           else if (so.getInletType() == IonSource::INFUSION)
03988           {
03989             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000060\" name=\"infusion\" />\n";
03990           }
03991           else if (so.getInletType() == IonSource::JETSEPARATOR)
03992           {
03993             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000061\" name=\"jet separator\" />\n";
03994           }
03995           else if (so.getInletType() == IonSource::MEMBRANESEPARATOR)
03996           {
03997             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000062\" name=\"membrane separator\" />\n";
03998           }
03999           else if (so.getInletType() == IonSource::MOVINGBELT)
04000           {
04001             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000063\" name=\"moving belt\" />\n";
04002           }
04003           else if (so.getInletType() == IonSource::MOVINGWIRE)
04004           {
04005             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000064\" name=\"moving wire\" />\n";
04006           }
04007           else if (so.getInletType() == IonSource::OPENSPLIT)
04008           {
04009             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000065\" name=\"open split\" />\n";
04010           }
04011           else if (so.getInletType() == IonSource::PARTICLEBEAM)
04012           {
04013             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000066\" name=\"particle beam\" />\n";
04014           }
04015           else if (so.getInletType() == IonSource::RESERVOIR)
04016           {
04017             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000067\" name=\"reservoir\" />\n";
04018           }
04019           else if (so.getInletType() == IonSource::SEPTUM)
04020           {
04021             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000068\" name=\"septum\" />\n";
04022           }
04023           else if (so.getInletType() == IonSource::THERMOSPRAYINLET)
04024           {
04025             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000069\" name=\"thermospray inlet\" />\n";
04026           }
04027           else if (so.getInletType() == IonSource::BATCH)
04028           {
04029             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000248\" name=\"direct insertion probe\" />\n";
04030           }
04031           else if (so.getInletType() == IonSource::CHROMATOGRAPHY)
04032           {
04033             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000249\" name=\"direct liquid introduction\" />\n";
04034           }
04035           else if (so.getInletType() == IonSource::MEMBRANE)
04036           {
04037             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000396\" name=\"membrane inlet\" />\n";
04038           }
04039           else if (so.getInletType() == IonSource::NANOSPRAY)
04040           {
04041             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000485\" name=\"nanospray inlet\" />\n";
04042           }
04043 
04044           if (so.getIonizationMethod() == IonSource::APCI)
04045           {
04046             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000070\" name=\"atmospheric pressure chemical ionization\" />\n";
04047           }
04048           else if (so.getIonizationMethod() == IonSource::CI)
04049           {
04050             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000071\" name=\"chemical ionization\" />\n";
04051           }
04052           else if (so.getIonizationMethod() == IonSource::ESI)
04053           {
04054             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000073\" name=\"electrospray ionization\" />\n";
04055           }
04056           else if (so.getIonizationMethod() == IonSource::FAB)
04057           {
04058             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000074\" name=\"fast atom bombardment ionization\" />\n";
04059           }
04060           else if (so.getIonizationMethod() == IonSource::MALDI)
04061           {
04062             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000075\" name=\"matrix-assisted laser desorption ionization\" />\n";
04063           }
04064           else if (so.getIonizationMethod() == IonSource::MPI)
04065           {
04066             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000227\" name=\"multiphoton ionization\" />\n";
04067           }
04068           else if (so.getIonizationMethod() == IonSource::AP_MALDI)
04069           {
04070             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000239\" name=\"atmospheric pressure matrix-assisted laser desorption ionization\" />\n";
04071           }
04072           else if (so.getIonizationMethod() == IonSource::API)
04073           {
04074             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000240\" name=\"atmospheric pressure ionization\" />\n";
04075           }
04076           else if (so.getIonizationMethod() == IonSource::DI)
04077           {
04078             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000247\" name=\"desorption ionization\" />\n";
04079           }
04080           else if (so.getIonizationMethod() == IonSource::FA)
04081           {
04082             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000255\" name=\"flowing afterglow\" />\n";
04083           }
04084           else if (so.getIonizationMethod() == IonSource::FD)
04085           {
04086             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000257\" name=\"field desorption\" />\n";
04087           }
04088           else if (so.getIonizationMethod() == IonSource::FI)
04089           {
04090             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000258\" name=\"field ionization\" />\n";
04091           }
04092           else if (so.getIonizationMethod() == IonSource::GD_MS)
04093           {
04094             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000259\" name=\"glow discharge ionization\" />\n";
04095           }
04096           else if (so.getIonizationMethod() == IonSource::NICI)
04097           {
04098             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000271\" name=\"Negative ion chemical ionization\" />\n";
04099           }
04100           else if (so.getIonizationMethod() == IonSource::NRMS)
04101           {
04102             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000272\" name=\"neutralization reionization mass spectrometry\" />\n";
04103           }
04104           else if (so.getIonizationMethod() == IonSource::PI)
04105           {
04106             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000273\" name=\"photoionization\" />\n";
04107           }
04108           else if (so.getIonizationMethod() == IonSource::PYMS)
04109           {
04110             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000274\" name=\"pyrolysis mass spectrometry\" />\n";
04111           }
04112           else if (so.getIonizationMethod() == IonSource::REMPI)
04113           {
04114             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000276\" name=\"resonance enhanced multiphoton ionization\" />\n";
04115           }
04116           else if (so.getIonizationMethod() == IonSource::SELDI)
04117           {
04118             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000278\" name=\"surface enhanced laser desorption ionization\" />\n";
04119           }
04120           else if (so.getIonizationMethod() == IonSource::SEND)
04121           {
04122             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000279\" name=\"surface enhanced neat desorption\" />\n";
04123           }
04124           else if (so.getIonizationMethod() == IonSource::AI)
04125           {
04126             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000380\" name=\"adiabatic ionization\" />\n";
04127           }
04128           else if (so.getIonizationMethod() == IonSource::ASI)
04129           {
04130             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000381\" name=\"associative ionization\" />\n";
04131           }
04132           else if (so.getIonizationMethod() == IonSource::APPI)
04133           {
04134             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000382\" name=\"atmospheric pressure photoionization\" />\n";
04135           }
04136           else if (so.getIonizationMethod() == IonSource::AD)
04137           {
04138             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000383\" name=\"autodetachment\" />\n";
04139           }
04140           else if (so.getIonizationMethod() == IonSource::AUI)
04141           {
04142             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000384\" name=\"autoionization\" />\n";
04143           }
04144           else if (so.getIonizationMethod() == IonSource::CEI)
04145           {
04146             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000385\" name=\"charge exchange ionization\" />\n";
04147           }
04148           else if (so.getIonizationMethod() == IonSource::CHEMI)
04149           {
04150             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000386\" name=\"chemi-ionization\" />\n";
04151           }
04152           else if (so.getIonizationMethod() == IonSource::SILI)
04153           {
04154             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000387\" name=\"desorption/ionization on silicon\" />\n";
04155           }
04156           else if (so.getIonizationMethod() == IonSource::DISSI)
04157           {
04158             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000388\" name=\"dissociative ionization\" />\n";
04159           }
04160           else if (so.getIonizationMethod() == IonSource::EI)
04161           {
04162             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000389\" name=\"electron ionization\" />\n";
04163           }
04164           else if (so.getIonizationMethod() == IonSource::LD)
04165           {
04166             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000393\" name=\"laser desorption ionization\" />\n";
04167           }
04168           else if (so.getIonizationMethod() == IonSource::LSI)
04169           {
04170             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000395\" name=\"liquid secondary ionization\" />\n";
04171           }
04172           else if (so.getIonizationMethod() == IonSource::MESI)
04173           {
04174             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000397\" name=\"microelectrospray\" />\n";
04175           }
04176           else if (so.getIonizationMethod() == IonSource::NESI)
04177           {
04178             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000398\" name=\"nanoelectrospray\" />\n";
04179           }
04180           else if (so.getIonizationMethod() == IonSource::PEI)
04181           {
04182             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000399\" name=\"penning ionization\" />\n";
04183           }
04184           else if (so.getIonizationMethod() == IonSource::PD)
04185           {
04186             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000400\" name=\"plasma desorption ionization\" />\n";
04187           }
04188           else if (so.getIonizationMethod() == IonSource::SI)
04189           {
04190             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000402\" name=\"secondary ionization\" />\n";
04191           }
04192           else if (so.getIonizationMethod() == IonSource::SOI)
04193           {
04194             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000403\" name=\"soft ionization\" />\n";
04195           }
04196           else if (so.getIonizationMethod() == IonSource::SPI)
04197           {
04198             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000404\" name=\"spark ionization\" />\n";
04199           }
04200           else if (so.getIonizationMethod() == IonSource::SALDI)
04201           {
04202             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000405\" name=\"surface-assisted laser desorption ionization\" />\n";
04203           }
04204           else if (so.getIonizationMethod() == IonSource::SUI)
04205           {
04206             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000406\" name=\"surface ionization\" />\n";
04207           }
04208           else if (so.getIonizationMethod() == IonSource::TI)
04209           {
04210             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000407\" name=\"thermal ionization\" />\n";
04211           }
04212           else if (so.getIonizationMethod() == IonSource::VI)
04213           {
04214             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000408\" name=\"vertical ionization\" />\n";
04215           }
04216           else if (so.getIonizationMethod() == IonSource::FIB)
04217           {
04218             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000446\" name=\"fast ion bombardment\" />\n";
04219           }
04220           else if (so.getIonizationMethod() == IonSource::IONMETHODNULL)
04221           {
04222             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000008\" name=\"ionization type\" />\n";
04223           }
04224 
04225           writeUserParam_(os, so, 5, "/mzML/instrumentConfigurationList/instrumentConfiguration/componentList/source/cvParam/@accession", validator);
04226           os << "\t\t\t\t</source>\n";
04227         }
04228         //FORCED
04229         if (component_count < 3 && in.getIonSources().empty())
04230         {
04231           os << "\t\t\t\t<source order=\"1234\">\n";
04232           os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000446\" name=\"fast ion bombardment\" />\n";
04233           os << "\t\t\t\t\t<userParam name=\"warning\" type=\"xsd:string\" value=\"invented ion source, to fulfill mzML schema\" />\n";
04234           os << "\t\t\t\t</source>\n";
04235         }
04236         //--------------------------------------------------------------------------------------------
04237         // mass analyzer
04238         //--------------------------------------------------------------------------------------------
04239         for (Size i = 0; i < in.getMassAnalyzers().size(); ++i)
04240         {
04241           const MassAnalyzer& ma = in.getMassAnalyzers()[i];
04242           os << "\t\t\t\t<analyzer order=\"" << ma.getOrder() << "\">\n";
04243 
04244           os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000014\" name=\"accuracy\" value=\"" << ma.getAccuracy() << "\" unitAccession=\"UO:0000169\" unitName=\"parts per million\" unitCvRef=\"UO\" />\n";
04245           // @todo: the parameters below are instrument specific and should not be written every time
04246           os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000022\" name=\"TOF Total Path Length\" value=\"" << ma.getTOFTotalPathLength() << "\" unitAccession=\"UO:0000008\" unitName=\"meter\" unitCvRef=\"UO\" />\n";
04247           os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000024\" name=\"final MS exponent\" value=\"" << ma.getFinalMSExponent() << "\" />\n";
04248           os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000025\" name=\"magnetic field strength\" value=\"" << ma.getMagneticFieldStrength() << "\" unitAccession=\"UO:0000228\" unitName=\"tesla\" unitCvRef=\"UO\" />\n";
04249 
04250           if (ma.getReflectronState() == MassAnalyzer::ON)
04251           {
04252             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000106\" name=\"reflectron on\" />\n";
04253 
04254           }
04255           else if (ma.getReflectronState() == MassAnalyzer::OFF)
04256           {
04257             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000105\" name=\"reflectron off\" />\n";
04258           }
04259 
04260           if (ma.getType() == MassAnalyzer::FOURIERTRANSFORM)
04261           {
04262             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000079\" name=\"fourier transform ion cyclotron resonance mass spectrometer\" />\n";
04263           }
04264           else if (ma.getType() == MassAnalyzer::SECTOR)
04265           {
04266             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000080\" name=\"magnetic sector\" />\n";
04267           }
04268           else if (ma.getType() == MassAnalyzer::QUADRUPOLE)
04269           {
04270             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000081\" name=\"quadrupole\" />\n";
04271           }
04272           else if (ma.getType() == MassAnalyzer::TOF)
04273           {
04274             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000084\" name=\"time-of-flight\" />\n";
04275           }
04276           else if (ma.getType() == MassAnalyzer::ESA)
04277           {
04278             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000254\" name=\"electrostatic energy analyzer\" />\n";
04279           }
04280           else if (ma.getType() == MassAnalyzer::IT)
04281           {
04282             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000264\" name=\"ion trap\" />\n";
04283           }
04284           else if (ma.getType() == MassAnalyzer::SWIFT)
04285           {
04286             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000284\" name=\"stored waveform inverse fourier transform\" />\n";
04287           }
04288           else if (ma.getType() == MassAnalyzer::CYCLOTRON)
04289           {
04290             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000288\" name=\"cyclotron\" />\n";
04291           }
04292           else if (ma.getType() == MassAnalyzer::ORBITRAP)
04293           {
04294             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000484\" name=\"orbitrap\" />\n";
04295           }
04296           else if (ma.getType() == MassAnalyzer::AXIALEJECTIONLINEARIONTRAP)
04297           {
04298             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000078\" name=\"axial ejection linear ion trap\" />\n";
04299           }
04300           else if (ma.getType() == MassAnalyzer::PAULIONTRAP)
04301           {
04302             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000082\" name=\"quadrupole ion trap\" />\n";
04303           }
04304           else if (ma.getType() == MassAnalyzer::RADIALEJECTIONLINEARIONTRAP)
04305           {
04306             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000083\" name=\"radial ejection linear ion trap\" />\n";
04307           }
04308           else if (ma.getType() == MassAnalyzer::LIT)
04309           {
04310             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000291\" name=\"linear ion trap\" />\n";
04311           }
04312           else if (ma.getType() == MassAnalyzer::ANALYZERNULL)
04313           {
04314             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000443\" name=\"mass analyzer type\" />\n";
04315           }
04316 
04317           writeUserParam_(os, ma, 5, "/mzML/instrumentConfigurationList/instrumentConfiguration/componentList/analyzer/cvParam/@accession", validator);
04318           os << "\t\t\t\t</analyzer>\n";
04319         }
04320         //FORCED
04321         if (component_count < 3 && in.getMassAnalyzers().empty())
04322         {
04323           os << "\t\t\t\t<analyzer order=\"1234\">\n";
04324           os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000288\" name=\"cyclotron\" />\n";
04325           os << "\t\t\t\t\t<userParam name=\"warning\" type=\"xsd:string\" value=\"invented mass analyzer, to fulfill mzML schema\" />\n";
04326           os << "\t\t\t\t</analyzer>\n";
04327         }
04328         //--------------------------------------------------------------------------------------------
04329         // ion detector
04330         //--------------------------------------------------------------------------------------------
04331         for (Size i = 0; i < in.getIonDetectors().size(); ++i)
04332         {
04333           const IonDetector& id = in.getIonDetectors()[i];
04334           os << "\t\t\t\t<detector order=\"" << id.getOrder() << "\">\n";
04335 
04336           os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000028\" name=\"detector resolution\" value=\"" << id.getResolution() << "\" />\n";
04337           os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000029\" name=\"sampling frequency\" value=\"" << id.getADCSamplingFrequency() << "\" unitAccession=\"UO:0000106\" unitName=\"hertz\" unitCvRef=\"UO\" />\n";
04338 
04339           if (id.getAcquisitionMode() == IonDetector::ADC)
04340           {
04341             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000117\" name=\"analog-digital converter\" />\n";
04342           }
04343           else if (id.getAcquisitionMode() == IonDetector::PULSECOUNTING)
04344           {
04345             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000118\" name=\"pulse counting\" />\n";
04346           }
04347           else if (id.getAcquisitionMode() == IonDetector::TDC)
04348           {
04349             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000119\" name=\"time-digital converter\" />\n";
04350           }
04351           else if (id.getAcquisitionMode() == IonDetector::TRANSIENTRECORDER)
04352           {
04353             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000120\" name=\"transient recorder\" />\n";
04354           }
04355 
04356           if (id.getType() == IonDetector::CHANNELTRON)
04357           {
04358             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000107\" name=\"channeltron\" />\n";
04359           }
04360           else if (id.getType() == IonDetector::DALYDETECTOR)
04361           {
04362             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000110\" name=\"daly detector\" />\n";
04363           }
04364           else if (id.getType() == IonDetector::FARADAYCUP)
04365           {
04366             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000112\" name=\"faraday cup\" />\n";
04367           }
04368           else if (id.getType() == IonDetector::MICROCHANNELPLATEDETECTOR)
04369           {
04370             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000114\" name=\"microchannel plate detector\" />\n";
04371           }
04372           else if (id.getType() == IonDetector::MULTICOLLECTOR)
04373           {
04374             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000115\" name=\"multi-collector\" />\n";
04375           }
04376           else if (id.getType() == IonDetector::PHOTOMULTIPLIER)
04377           {
04378             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000116\" name=\"photomultiplier\" />\n";
04379           }
04380           else if (id.getType() == IonDetector::ELECTRONMULTIPLIER)
04381           {
04382             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000253\" name=\"electron multiplier\" />\n";
04383           }
04384           else if (id.getType() == IonDetector::ARRAYDETECTOR)
04385           {
04386             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000345\" name=\"array detector\" />\n";
04387           }
04388           else if (id.getType() == IonDetector::CONVERSIONDYNODE)
04389           {
04390             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000346\" name=\"conversion dynode\" />\n";
04391           }
04392           else if (id.getType() == IonDetector::DYNODE)
04393           {
04394             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000347\" name=\"dynode\" />\n";
04395           }
04396           else if (id.getType() == IonDetector::FOCALPLANECOLLECTOR)
04397           {
04398             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000348\" name=\"focal plane collector\" />\n";
04399           }
04400           else if (id.getType() == IonDetector::IONTOPHOTONDETECTOR)
04401           {
04402             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000349\" name=\"ion-to-photon detector\" />\n";
04403           }
04404           else if (id.getType() == IonDetector::POINTCOLLECTOR)
04405           {
04406             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000350\" name=\"point collector\" />\n";
04407           }
04408           else if (id.getType() == IonDetector::POSTACCELERATIONDETECTOR)
04409           {
04410             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000351\" name=\"postacceleration detector\" />\n";
04411           }
04412           else if (id.getType() == IonDetector::PHOTODIODEARRAYDETECTOR)
04413           {
04414             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000621\" name=\"photodiode array detector\" />\n";
04415           }
04416           else if (id.getType() == IonDetector::INDUCTIVEDETECTOR)
04417           {
04418             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000624\" name=\"inductive detector\" />\n";
04419           }
04420           else if (id.getType() == IonDetector::CONVERSIONDYNODEELECTRONMULTIPLIER)
04421           {
04422             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000108\" name=\"conversion dynode electron multiplier\" />\n";
04423           }
04424           else if (id.getType() == IonDetector::CONVERSIONDYNODEPHOTOMULTIPLIER)
04425           {
04426             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000109\" name=\"conversion dynode photomultiplier\" />\n";
04427           }
04428           else if (id.getType() == IonDetector::ELECTRONMULTIPLIERTUBE)
04429           {
04430             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000111\" name=\"electron multiplier tube\" />\n";
04431           }
04432           else if (id.getType() == IonDetector::FOCALPLANEARRAY)
04433           {
04434             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000113\" name=\"focal plane array\" />\n";
04435           }
04436           else if (id.getType() == IonDetector::TYPENULL)
04437           {
04438             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000026\" name=\"detector type\" />\n";
04439           }
04440 
04441           writeUserParam_(os, id, 5, "/mzML/instrumentConfigurationList/instrumentConfiguration/componentList/detector/cvParam/@accession", validator);
04442           os << "\t\t\t\t</detector>\n";
04443         }
04444         //FORCED
04445         if (component_count < 3 && in.getIonDetectors().empty())
04446         {
04447           os << "\t\t\t\t<detector order=\"1234\">\n";
04448           os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000107\" name=\"channeltron\" />\n";
04449           os << "\t\t\t\t\t<userParam name=\"warning\" type=\"xsd:string\" value=\"invented ion detector, to fulfill mzML schema\" />\n";
04450           os << "\t\t\t\t</detector>\n";
04451         }
04452         os << "\t\t\t</componentList>\n";
04453       }
04454       os << "\t\t\t<softwareRef ref=\"so_in_0\" />\n";
04455       os << "\t\t</instrumentConfiguration>\n";
04456       os << "\t</instrumentConfigurationList>\n";
04457 
04458       //--------------------------------------------------------------------------------------------
04459       // data processing
04460       //--------------------------------------------------------------------------------------------
04461 
04462       // count number of float data array dps
04463       Size num_bi_dps(0);
04464       for (Size s = 0; s < exp.size(); ++s)
04465       {
04466         for (Size m = 0; m < exp[s].getFloatDataArrays().size(); ++m)
04467         {
04468           ++num_bi_dps;
04469         }
04470       }
04471 
04472       os << "\t<dataProcessingList count=\"" << (std::max)((Size)1, dps.size() + num_bi_dps) << "\">\n";
04473       //default (first spectrum data or fictional data)
04474       if (exp.empty())
04475       {
04476         std::vector<DataProcessing> dummy;
04477         writeDataProcessing_(os, "dp_sp_0", dummy, validator);
04478       }
04479 
04480       for (Size s = 0; s < dps.size(); ++s)
04481       {
04482         writeDataProcessing_(os, String("dp_sp_") + s, dps[s], validator);
04483       }
04484 
04485       //for each binary data array
04486       for (Size s = 0; s < exp.size(); ++s)
04487       {
04488         for (Size m = 0; m < exp[s].getFloatDataArrays().size(); ++m)
04489         {
04490           writeDataProcessing_(os, String("dp_sp_") + s + "_bi_" + m, exp[s].getFloatDataArrays()[m].getDataProcessing(), validator);
04491         }
04492       }
04493 
04494       os << "\t</dataProcessingList>\n";
04495       //--------------------------------------------------------------------------------------------
04496       // acquisitionSettings
04497       //--------------------------------------------------------------------------------------------
04498 
04499       //--------------------------------------------------------------------------------------------
04500       // run
04501       //--------------------------------------------------------------------------------------------
04502       os << "\t<run id=\"ru_0\" defaultInstrumentConfigurationRef=\"ic_0\" sampleRef=\"sa_0\"";
04503       if (exp.getDateTime().isValid())
04504       {
04505         os << " startTimeStamp=\"" << exp.getDateTime().get().substitute(' ', 'T') << "\"";
04506       }
04507       if (exp.getSourceFiles().size() > 0)
04508       {
04509         os << " defaultSourceFileRef=\"sf_ru_0\"";
04510       }
04511       os << ">\n";
04512 
04513       //run attributes
04514       if (exp.getFractionIdentifier() != "")
04515       {
04516         os << "\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000858\" name=\"fraction identifier\" value=\"" << exp.getFractionIdentifier() << "\" />\n";
04517       }
04518 
04519       writeUserParam_(os, exp, 2, "/mzML/run/cvParam/@accession", validator);
04520 
04521       //--------------------------------------------------------------------------------------------
04522       //spectrum
04523       //--------------------------------------------------------------------------------------------
04524       if (exp.size() != 0)
04525       {
04526         // INFO : do not try to be smart and skip empty spectra or
04527         // chromatograms. There can be very good reasons for this (e.g. if the
04528         // meta information needs to be stored here but the actual data is
04529         // stored somewhere else).
04530         os << "\t\t<spectrumList count=\"" << exp.size() << "\" defaultDataProcessingRef=\"dp_sp_0\">\n";
04531 
04532         //check native ids
04533         bool renew_native_ids = false;
04534         for (Size s = 0; s < exp.size(); ++s)
04535         {
04536           if (!exp[s].getNativeID().has('='))
04537           {
04538             renew_native_ids = true;
04539             break;
04540           }
04541         }
04542         //issue warning if something is wrong
04543         if (renew_native_ids)
04544         {
04545           warning(STORE, String("Invalid native IDs detected. Using spectrum identifier nativeID format (spectrum=xsd:nonNegativeInteger) for all spectra."));
04546         }
04547 
04548         //write actual data
04549         for (Size s = 0; s < exp.size(); ++s)
04550         {
04551           logger_.setProgress(progress++);
04552           const SpectrumType& spec = exp[s];
04553 
04554           //native id
04555           String native_id = spec.getNativeID();
04556           if (renew_native_ids)
04557             native_id = String("spectrum=") + s;
04558 
04559           os << "\t\t\t<spectrum id=\"" << native_id << "\" index=\"" << s << "\" defaultArrayLength=\"" << spec.size() << "\"";
04560           if (spec.getSourceFile() != SourceFile())
04561           {
04562             os << " sourceFileRef=\"sf_sp_" << s << "\"";
04563           }
04564           //the data processing info of the first spectrum is the default
04565           //if (s==0 || spec.getDataProcessing()!=exp[0].getDataProcessing())
04566           if (s == 0 || spec.getDataProcessing() != dps[0])
04567           {
04568             Size dp_ref_num = s;
04569             if (s != 0)
04570             {
04571               for (Size i = 0; i < dps.size(); ++i)
04572               {
04573                 if (spec.getDataProcessing() == dps[i])
04574                 {
04575                   dp_ref_num = i;
04576                   break;
04577                 }
04578               }
04579             }
04580             os << " dataProcessingRef=\"dp_sp_" << dp_ref_num << "\"";
04581           }
04582           os << ">\n";
04583 
04584           //spectrum representation
04585           if (spec.getType() == SpectrumSettings::PEAKS)
04586           {
04587             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000127\" name=\"centroid spectrum\" />\n";
04588           }
04589           else if (spec.getType() == SpectrumSettings::RAWDATA)
04590           {
04591             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000128\" name=\"profile spectrum\" />\n";
04592           }
04593           else
04594           {
04595             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000525\" name=\"spectrum representation\" />\n";
04596           }
04597 
04598           //spectrum attributes
04599           if (spec.getMSLevel() != 0)
04600           {
04601             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000511\" name=\"ms level\" value=\"" << spec.getMSLevel() << "\" />\n";
04602           }
04603           if (spec.getInstrumentSettings().getZoomScan())
04604           {
04605             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000497\" name=\"zoom scan\" />\n";
04606           }
04607 
04608           //spectrum type
04609           if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::MASSSPECTRUM)
04610           {
04611             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000294\" name=\"mass spectrum\" />\n";
04612           }
04613           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::MS1SPECTRUM)
04614           {
04615             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000579\" name=\"MS1 spectrum\" />\n";
04616           }
04617           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::MSNSPECTRUM)
04618           {
04619             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000580\" name=\"MSn spectrum\" />\n";
04620           }
04621           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::SIM)
04622           {
04623             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000582\" name=\"SIM spectrum\" />\n";
04624           }
04625           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::SRM)
04626           {
04627             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000583\" name=\"SRM spectrum\" />\n";
04628           }
04629           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::CRM)
04630           {
04631             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000581\" name=\"CRM spectrum\" />\n";
04632           }
04633           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::PRECURSOR)
04634           {
04635             os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000341\" name=\"precursor ion spectrum\" />\n";
04636           }
04637           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::CNG)
04638           {
04639             os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000325\" name=\"constant neutral gain spectrum\" />\n";
04640           }
04641           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::CNL)
04642           {
04643             os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000326\" name=\"constant neutral loss spectrum\" />\n";
04644           }
04645           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::EMR)
04646           {
04647             os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000804\" name=\"electromagnetic radiation spectrum\" />\n";
04648           }
04649           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::EMISSION)
04650           {
04651             os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000805\" name=\"emission spectrum\" />\n";
04652           }
04653           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::ABSORBTION)
04654           {
04655             os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000806\" name=\"absorption spectrum\" />\n";
04656           }
04657           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::EMC)
04658           {
04659             os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000789\" name=\"enhanced multiply charged spectrum\" />\n";
04660           }
04661           else if (spec.getInstrumentSettings().getScanMode() == InstrumentSettings::TDF)
04662           {
04663             os << "\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000789\" name=\"time-delayed fragmentation spectrum\" />\n";
04664           }
04665           else           //FORCED
04666           {
04667             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000294\" name=\"mass spectrum\" />\n";
04668           }
04669 
04670           //scan polarity
04671           if (spec.getInstrumentSettings().getPolarity() == IonSource::NEGATIVE)
04672           {
04673             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000129\" name=\"negative scan\" />\n";
04674           }
04675           else if (spec.getInstrumentSettings().getPolarity() == IonSource::POSITIVE)
04676           {
04677             os << "\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000130\" name=\"positive scan\" />\n";
04678           }
04679 
04680           writeUserParam_(os, spec, 4, "/mzML/run/spectrumList/spectrum/cvParam/@accession", validator);
04681           //--------------------------------------------------------------------------------------------
04682           //scan list
04683           //--------------------------------------------------------------------------------------------
04684           os << "\t\t\t\t<scanList count=\"" << (std::max)((Size)1, spec.getAcquisitionInfo().size()) << "\">\n";
04685           ControlledVocabulary::CVTerm ai_term = getChildWithName_("MS:1000570", spec.getAcquisitionInfo().getMethodOfCombination());
04686           if (ai_term.id != "")
04687           {
04688             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"" << ai_term.id << "\" name=\"" << ai_term.name << "\" />\n";
04689           }
04690           else
04691           {
04692             os << "\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000795\" name=\"no combination\" />\n";
04693           }
04694           writeUserParam_(os, spec.getAcquisitionInfo(), 5, "/mzML/run/spectrumList/spectrum/scanList/cvParam/@accession", validator);
04695 
04696           //--------------------------------------------------------------------------------------------
04697           //scan
04698           //--------------------------------------------------------------------------------------------
04699           for (Size j = 0; j < spec.getAcquisitionInfo().size(); ++j)
04700           {
04701             const Acquisition& ac = spec.getAcquisitionInfo()[j];
04702             os << "\t\t\t\t\t<scan ";
04703             if (ac.getIdentifier() != "")
04704               os << "externalSpectrumID=\"" << ac.getIdentifier() << "\"";
04705             os << ">\n";
04706             if (j == 0)
04707             {
04708               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000016\" name=\"scan start time\" value=\"" << spec.getRT() << "\" unitAccession=\"UO:0000010\" unitName=\"second\" unitCvRef=\"UO\" />\n";
04709             }
04710             writeUserParam_(os, ac, 6, "/mzML/run/spectrumList/spectrum/scanList/scan/cvParam/@accession", validator);
04711             //scan windows
04712             if (j == 0 && spec.getInstrumentSettings().getScanWindows().size() != 0)
04713             {
04714               os << "\t\t\t\t\t\t<scanWindowList count=\"" << spec.getInstrumentSettings().getScanWindows().size() << "\">\n";
04715               for (Size j = 0; j < spec.getInstrumentSettings().getScanWindows().size(); ++j)
04716               {
04717                 os << "\t\t\t\t\t\t\t<scanWindow>\n";
04718                 os << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000501\" name=\"scan window lower limit\" value=\"" << spec.getInstrumentSettings().getScanWindows()[j].begin << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04719                 os << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000500\" name=\"scan window upper limit\" value=\"" << spec.getInstrumentSettings().getScanWindows()[j].end << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04720                 writeUserParam_(os, spec.getInstrumentSettings().getScanWindows()[j], 8, "/mzML/run/spectrumList/spectrum/scanList/scan/scanWindowList/scanWindow/cvParam/@accession", validator);
04721                 os << "\t\t\t\t\t\t\t</scanWindow>\n";
04722               }
04723               os << "\t\t\t\t\t\t</scanWindowList>\n";
04724             }
04725             os << "\t\t\t\t\t</scan>\n";
04726           }
04727           //fallback if we have no acquisition information (a dummy scan is created for RT and so on)
04728           if (spec.getAcquisitionInfo().empty())
04729           {
04730             os << "\t\t\t\t\t<scan>\n";
04731             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000016\" name=\"scan start time\" value=\"" << spec.getRT() << "\" unitAccession=\"UO:0000010\" unitName=\"second\" unitCvRef=\"UO\" />\n";
04732             //scan windows
04733             if (spec.getInstrumentSettings().getScanWindows().size() != 0)
04734             {
04735               os << "\t\t\t\t\t\t<scanWindowList count=\"" << spec.getInstrumentSettings().getScanWindows().size() << "\">\n";
04736               for (Size j = 0; j < spec.getInstrumentSettings().getScanWindows().size(); ++j)
04737               {
04738                 os << "\t\t\t\t\t\t\t<scanWindow>\n";
04739                 os << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000501\" name=\"scan window lower limit\" value=\"" << spec.getInstrumentSettings().getScanWindows()[j].begin << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04740                 os << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000500\" name=\"scan window upper limit\" value=\"" << spec.getInstrumentSettings().getScanWindows()[j].end << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04741                 writeUserParam_(os, spec.getInstrumentSettings().getScanWindows()[j], 8, "/mzML/run/spectrumList/spectrum/scanList/scan/scanWindowList/scanWindow/cvParam/@accession", validator);
04742                 os << "\t\t\t\t\t\t\t</scanWindow>\n";
04743               }
04744               os << "\t\t\t\t\t\t</scanWindowList>\n";
04745             }
04746             os << "\t\t\t\t\t</scan>\n";
04747           }
04748           os << "\t\t\t\t</scanList>\n";
04749           //--------------------------------------------------------------------------------------------
04750           //precursor list
04751           //--------------------------------------------------------------------------------------------
04752           if (!spec.getPrecursors().empty())
04753           {
04754             os << "\t\t\t<precursorList count=\"" << spec.getPrecursors().size() << "\">\n";
04755             for (Size p = 0; p != spec.getPrecursors().size(); ++p)
04756             {
04757               writePrecursor_(os, spec.getPrecursors()[p], validator);
04758             }
04759             os << "\t\t\t</precursorList>\n";
04760           }
04761 /*
04762                     if (spec.getPrecursors().size()!=0)
04763                     {
04764                         os\t<< "\t\t\t\t<precursorList count=\"" << spec.getPrecursors().size() << "\">\n";
04765                         for (Size p=0; p<spec.getPrecursors().size(); ++p)
04766                         {
04767                             const Precursor& precursor = spec.getPrecursors()[p];
04768                             os\t<< "\t\t\t\t\t<precursor>\n";
04769                             //--------------------------------------------------------------------------------------------
04770                             //isolation window
04771                             //--------------------------------------------------------------------------------------------
04772                             os\t<< "\t\t\t\t\t\t<isolationWindow>\n";
04773                             os  << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000827\" name=\"isolation window target m/z\" value=\"" << precursor.getMZ() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04774                             os  << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000828\" name=\"isolation window lower offset\" value=\"" << precursor.getIsolationWindowLowerOffset() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04775                             os  << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000829\" name=\"isolation window upper offset\" value=\"" << precursor.getIsolationWindowUpperOffset() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04776                             os\t<< "\t\t\t\t\t\t</isolationWindow>\n";
04777                             //userParam: no extra object for it => no user paramters
04778 
04779                             //--------------------------------------------------------------------------------------------
04780                             //selected ion list
04781                             //--------------------------------------------------------------------------------------------
04782                             os\t<< "\t\t\t\t\t\t<selectedIonList count=\"1\">\n";
04783                             os\t<< "\t\t\t\t\t\t\t<selectedIon>\n";
04784                             os  << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000744\" name=\"selected ion m/z\" value=\"" << precursor.getMZ() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04785                             os  << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000041\" name=\"charge state\" value=\"" << precursor.getCharge() << "\" />\n";
04786                             os  << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000042\" name=\"peak intensity\" value=\"" << precursor.getIntensity() << "\" unitAccession=\"MS:1000132\" unitName=\"percent of base peak\" unitCvRef=\"MS\" />\n";
04787                             for (Size j=0; j<precursor.getPossibleChargeStates().size(); ++j)
04788                             {
04789                                 os  << "\t\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000633\" name=\"possible charge state\" value=\"" << precursor.getPossibleChargeStates()[j] << "\" />\n";
04790                             }
04791                             //userParam: no extra object for it => no user paramters
04792                             os\t<< "\t\t\t\t\t\t\t</selectedIon>\n";
04793                             os\t<< "\t\t\t\t\t\t</selectedIonList>\n";
04794 
04795                             //--------------------------------------------------------------------------------------------
04796                             //activation
04797                             //--------------------------------------------------------------------------------------------
04798                             os\t<< "\t\t\t\t\t\t<activation>\n";
04799                             os  << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000509\" name=\"activation energy\" value=\"" << precursor.getActivationEnergy() << "\" unitAccession=\"UO:0000266\" unitName=\"electronvolt\" unitCvRef=\"UO\" />\n";
04800                             if (precursor.getActivationMethods().count(Precursor::CID)!=0)
04801                             {
04802                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000133\" name=\"collision-induced dissociation\" />\n";
04803                             }
04804                             if (precursor.getActivationMethods().count(Precursor::PD)!=0)
04805                             {
04806                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000134\" name=\"plasma desorption\" />\n";
04807                             }
04808                             if (precursor.getActivationMethods().count(Precursor::PSD)!=0)
04809                             {
04810                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000135\" name=\"post-source decay\" />\n";
04811                             }
04812                             if (precursor.getActivationMethods().count(Precursor::SID)!=0)
04813                             {
04814                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000136\" name=\"surface-induced dissociation\" />\n";
04815                             }
04816                             if (precursor.getActivationMethods().count(Precursor::BIRD)!=0)
04817                             {
04818                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000242\" name=\"blackbody infrared radiative dissociation\" />\n";
04819                             }
04820                             if (precursor.getActivationMethods().count(Precursor::ECD)!=0)
04821                             {
04822                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000250\" name=\"electron capture dissociation\" />\n";
04823                             }
04824                             if (precursor.getActivationMethods().count(Precursor::IMD)!=0)
04825                             {
04826                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000262\" name=\"infrared multiphoton dissociation\" />\n";
04827                             }
04828                             if (precursor.getActivationMethods().count(Precursor::SORI)!=0)
04829                             {
04830                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000282\" name=\"sustained off-resonance irradiation\" />\n";
04831                             }
04832                             if (precursor.getActivationMethods().count(Precursor::HCID)!=0)
04833                             {
04834                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000422\" name=\"high-energy collision-induced dissociation\" />\n";
04835                             }
04836                             if (precursor.getActivationMethods().count(Precursor::LCID)!=0)
04837                             {
04838                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000433\" name=\"low-energy collision-induced dissociation\" />\n";
04839                             }
04840                             if (precursor.getActivationMethods().count(Precursor::PHD)!=0)
04841                             {
04842                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000435\" name=\"photodissociation\" />\n";
04843                             }
04844                             if (precursor.getActivationMethods().count(Precursor::ETD)!=0)
04845                             {
04846                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000598\" name=\"electron transfer dissociation\" />\n";
04847                             }
04848                             if (precursor.getActivationMethods().count(Precursor::PQD)!=0)
04849                             {
04850                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000599\" name=\"pulsed q dissociation\" />\n";
04851                             }
04852                             if (precursor.getActivationMethods().empty())
04853                             {
04854                                 os  << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000044\" name=\"dissociation method\" />\n";
04855                             }
04856                             //as "precursor" has no own user param its userParam is stored here
04857                             writeUserParam_(os, precursor, 6);
04858                             os\t<< "\t\t\t\t\t</activation>\n";
04859                             os\t<< "\t\t\t\t</precursor>\n";
04860                         }
04861                         os\t<< "\t\t\t</precursorList>\n";
04862                     }
04863 */
04864           //--------------------------------------------------------------------------------------------
04865           //product list
04866           //--------------------------------------------------------------------------------------------
04867           if (spec.getProducts().size() != 0)
04868           {
04869             os << "\t\t\t\t<productList count=\"" << spec.getProducts().size() << "\">\n";
04870             for (Size p = 0; p < spec.getProducts().size(); ++p)
04871             {
04872               writeProduct_(os, spec.getProducts()[p], validator);
04873             }
04874             os << "\t\t\t\t</productList>\n";
04875           }
04876 /*
04877                     if (spec.getProducts().size()!=0)
04878                     {
04879                         os\t<< "\t\t\t\t<productList count=\"" << spec.getProducts().size() << "\">\n";
04880                         for (Size p=0; p<spec.getProducts().size(); ++p)
04881                         {
04882                             os\t<< "\t\t\t\t\t<product>\n";
04883                             os\t<< "\t\t\t\t\t\t<isolationWindow>\n";
04884                             os  << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000827\" name=\"isolation window target m/z\" value=\"" << spec.getProducts()[p].getMZ() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04885                             os  << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000828\" name=\"isolation window lower offset\" value=\"" << spec.getProducts()[p].getIsolationWindowLowerOffset() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04886                             os  << "\t\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000829\" name=\"isolation window upper offset\" value=\"" << spec.getProducts()[p].getIsolationWindowUpperOffset() << "\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04887                             writeUserParam_(os, spec.getProducts()[p], 7);
04888                             os\t<< "\t\t\t\t\t\t</isolationWindow>\n";
04889                             os\t<< "\t\t\t\t</product>\n";
04890                         }
04891                         os\t<< "\t\t\t</productList>\n";
04892                     }
04893 */
04894 
04895           //--------------------------------------------------------------------------------------------
04896           //binary data array list
04897           //--------------------------------------------------------------------------------------------
04898           if (spec.size() != 0)
04899           {
04900             String compression_term;
04901             if (options_.getCompression())
04902             {
04903               compression_term = "<cvParam cvRef=\"MS\" accession=\"MS:1000574\" name=\"zlib compression\" />";
04904             }
04905             else
04906             {
04907               compression_term = "<cvParam cvRef=\"MS\" accession=\"MS:1000576\" name=\"no compression\" />";
04908             }
04909             String encoded_string;
04910             os << "\t\t\t\t<binaryDataArrayList count=\"" << (2 + spec.getFloatDataArrays().size() + spec.getStringDataArrays().size() + spec.getIntegerDataArrays().size()) << "\">\n";
04911             //write m/z array (default 64 bit precision)
04912             {
04913 
04914               if (options_.getMz32Bit())
04915               {
04916                 std::vector<Real> data_to_encode(spec.size());
04917                 for (Size p = 0; p < spec.size(); ++p)
04918                   data_to_encode[p] = spec[p].getMZ();
04919                 decoder_.encode(data_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
04920                 os << "\t\t\t\t\t<binaryDataArray encodedLength=\"" << encoded_string.size() << "\">\n";
04921                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000514\" name=\"m/z array\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04922                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000521\" name=\"32-bit float\" />\n";
04923               }
04924               else
04925               {
04926                 std::vector<DoubleReal> data_to_encode(spec.size());
04927                 for (Size p = 0; p < spec.size(); ++p)
04928                   data_to_encode[p] = spec[p].getMZ();
04929                 decoder_.encode(data_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
04930                 os << "\t\t\t\t\t<binaryDataArray encodedLength=\"" << encoded_string.size() << "\">\n";
04931                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000514\" name=\"m/z array\" unitAccession=\"MS:1000040\" unitName=\"m/z\" unitCvRef=\"MS\" />\n";
04932                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000523\" name=\"64-bit float\" />\n";
04933               }
04934 
04935               os << "\t\t\t\t\t\t" << compression_term << "\n";
04936               os << "\t\t\t\t\t\t<binary>" << encoded_string << "</binary>\n";
04937               os << "\t\t\t\t\t</binaryDataArray>\n";
04938             }
04939             //write intensity array (default 32 bit precision)
04940             {
04941 
04942               if (options_.getIntensity32Bit())
04943               {
04944                 std::vector<Real> data_to_encode(spec.size());
04945                 for (Size p = 0; p < spec.size(); ++p)
04946                   data_to_encode[p] = spec[p].getIntensity();
04947                 decoder_.encode(data_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
04948                 os << "\t\t\t\t\t<binaryDataArray encodedLength=\"" << encoded_string.size() << "\">\n";
04949                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000515\" name=\"intensity array\" unitAccession=\"MS:1000131\" unitName=\"number of counts\" unitCvRef=\"MS\"/>\n";
04950                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000521\" name=\"32-bit float\" />\n";
04951               }
04952               else
04953               {
04954                 std::vector<DoubleReal> data_to_encode(spec.size());
04955                 for (Size p = 0; p < spec.size(); ++p)
04956                   data_to_encode[p] = spec[p].getIntensity();
04957                 decoder_.encode(data_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
04958                 os << "\t\t\t\t\t<binaryDataArray encodedLength=\"" << encoded_string.size() << "\">\n";
04959                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000515\" name=\"intensity array\" unitAccession=\"MS:1000131\" unitName=\"number of counts\" unitCvRef=\"MS\"/>\n";
04960                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000523\" name=\"64-bit float\" />\n";
04961               }
04962               os << "\t\t\t\t\t\t" << compression_term << "\n";
04963               os << "\t\t\t\t\t\t<binary>" << encoded_string << "</binary>\n";
04964               os << "\t\t\t\t\t</binaryDataArray>\n";
04965             }
04966             //write float data array
04967             for (Size m = 0; m < spec.getFloatDataArrays().size(); ++m)
04968             {
04969               const typename SpectrumType::FloatDataArray& array = spec.getFloatDataArrays()[m];
04970               std::vector<DoubleReal> data64_to_encode(array.size());
04971               for (Size p = 0; p < array.size(); ++p)
04972                 data64_to_encode[p] = array[p];
04973               decoder_.encode(data64_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
04974               String data_processing_ref_string = "";
04975               if (array.getDataProcessing().size() != 0)
04976               {
04977                 data_processing_ref_string = String("dataProcessingRef=\"dp_sp_") + s + "_bi_" + m + "\"";
04978               }
04979               os << "\t\t\t\t\t<binaryDataArray arrayLength=\"" << array.size() << "\" encodedLength=\"" << encoded_string.size() << "\" " << data_processing_ref_string << ">\n";
04980               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000523\" name=\"64-bit float\" />\n";
04981               os << "\t\t\t\t\t\t" << compression_term << "\n";
04982               ControlledVocabulary::CVTerm bi_term = getChildWithName_("MS:1000513", array.getName());
04983               if (bi_term.id != "")
04984               {
04985                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"" << bi_term.id << "\" name=\"" << bi_term.name << "\" />\n";
04986               }
04987               else
04988               {
04989                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000786\" name=\"non-standard data array\" value=\"" << array.getName() << "\" />\n";
04990               }
04991               writeUserParam_(os, array, 6, "/mzML/run/spectrumList/spectrum/binaryDataArrayList/binaryDataArray/cvParam/@accession", validator);
04992               os << "\t\t\t\t\t\t<binary>" << encoded_string << "</binary>\n";
04993               os << "\t\t\t\t\t</binaryDataArray>\n";
04994             }
04995             //write integer data array
04996             for (Size m = 0; m < spec.getIntegerDataArrays().size(); ++m)
04997             {
04998               const typename SpectrumType::IntegerDataArray& array = spec.getIntegerDataArrays()[m];
04999               std::vector<Int64> data64_to_encode(array.size());
05000               for (Size p = 0; p < array.size(); ++p)
05001                 data64_to_encode[p] = array[p];
05002               decoder_.encodeIntegers(data64_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
05003               String data_processing_ref_string = "";
05004               if (array.getDataProcessing().size() != 0)
05005               {
05006                 data_processing_ref_string = String("dataProcessingRef=\"dp_sp_") + s + "_bi_" + m + "\"";
05007               }
05008               os << "\t\t\t\t\t<binaryDataArray arrayLength=\"" << array.size() << "\" encodedLength=\"" << encoded_string.size() << "\" " << data_processing_ref_string << ">\n";
05009               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000522\" name=\"64-bit integer\" />\n";
05010               os << "\t\t\t\t\t\t" << compression_term << "\n";
05011               ControlledVocabulary::CVTerm bi_term = getChildWithName_("MS:1000513", array.getName());
05012               if (bi_term.id != "")
05013               {
05014                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"" << bi_term.id << "\" name=\"" << bi_term.name << "\" />\n";
05015               }
05016               else
05017               {
05018                 os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000786\" name=\"non-standard data array\" value=\"" << array.getName() << "\" />\n";
05019               }
05020               writeUserParam_(os, array, 6, "/mzML/run/spectrumList/spectrum/binaryDataArrayList/binaryDataArray/cvParam/@accession", validator);
05021               os << "\t\t\t\t\t\t<binary>" << encoded_string << "</binary>\n";
05022               os << "\t\t\t\t\t</binaryDataArray>\n";
05023             }
05024             //write string data arrays
05025             for (Size m = 0; m < spec.getStringDataArrays().size(); ++m)
05026             {
05027               const typename SpectrumType::StringDataArray& array = spec.getStringDataArrays()[m];
05028               std::vector<String> data_to_encode;
05029               data_to_encode.resize(array.size());
05030               for (Size p = 0; p < array.size(); ++p)
05031                 data_to_encode[p] = array[p];
05032               decoder_.encodeStrings(data_to_encode, encoded_string, options_.getCompression());
05033               String data_processing_ref_string = "";
05034               if (array.getDataProcessing().size() != 0)
05035               {
05036                 data_processing_ref_string = String("dataProcessingRef=\"dp_sp_") + s + "_bi_" + m + "\"";
05037               }
05038               os << "\t\t\t\t\t<binaryDataArray arrayLength=\"" << array.size() << "\" encodedLength=\"" << encoded_string.size() << "\" " << data_processing_ref_string << ">\n";
05039               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1001479\" name=\"null-terminated ASCII string\" />\n";
05040               os << "\t\t\t\t\t\t" << compression_term << "\n";
05041               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000786\" name=\"non-standard data array\" value=\"" << array.getName() << "\" />\n";
05042               writeUserParam_(os, array, 6, "/mzML/run/spectrumList/spectrum/binaryDataArrayList/binaryDataArray/cvParam/@accession", validator);
05043               os << "\t\t\t\t\t\t<binary>" << encoded_string << "</binary>\n";
05044               os << "\t\t\t\t\t</binaryDataArray>\n";
05045             }
05046             os << "\t\t\t\t</binaryDataArrayList>\n";
05047           }
05048 
05049           os << "\t\t\t</spectrum>\n";
05050         }
05051         os << "\t\t</spectrumList>\n";
05052       }
05053 
05054       //--------------------------------------------------------------------------------------------
05055       //chromatograms
05056       //--------------------------------------------------------------------------------------------
05057       if (!exp.getChromatograms().empty())
05058       {
05059         // INFO : do not try to be smart and skip empty spectra or
05060         // chromatograms. There can be very good reasons for this (e.g. if the
05061         // meta information needs to be stored here but the actual data is
05062         // stored somewhere else).
05063         os << "\t\t<chromatogramList count=\"" << exp.getChromatograms().size() << "\" defaultDataProcessingRef=\"dp_sp_0\">\n";
05064         for (Size c = 0; c != exp.getChromatograms().size(); ++c)
05065         {
05066           logger_.setProgress(progress++);
05067           // TODO native id with chromatogram=?? prefix?
05068           const ChromatogramType& chromatogram = exp.getChromatograms()[c];
05069           os << "      <chromatogram id=\"" << chromatogram.getNativeID() << "\" index=\"" << c << "\" defaultArrayLength=\"" << chromatogram.size() << "\">" << "\n";
05070 
05071           // write cvParams (chromatogram type)
05072           if (chromatogram.getChromatogramType() == ChromatogramSettings::MASS_CHROMATOGRAM)
05073           {
05074             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000810\" name=\"mass chromatogram\" />\n";
05075           }
05076           else if (chromatogram.getChromatogramType() == ChromatogramSettings::TOTAL_ION_CURRENT_CHROMATOGRAM)
05077           {
05078             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000235\" name=\"total ion current chromatogram\" />\n";
05079           }
05080           else if (chromatogram.getChromatogramType() == ChromatogramSettings::SELECTED_ION_CURRENT_CHROMATOGRAM)
05081           {
05082             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000627\" name=\"selected ion current chromatogram\" />\n";
05083           }
05084           else if (chromatogram.getChromatogramType() == ChromatogramSettings::BASEPEAK_CHROMATOGRAM)
05085           {
05086             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000628\" name=\"basepeak chromatogram\" />\n";
05087           }
05088           else if (chromatogram.getChromatogramType() == ChromatogramSettings::SELECTED_ION_MONITORING_CHROMATOGRAM)
05089           {
05090             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1001472\" name=\"selected ion monitoring chromatogram\" />\n";
05091           }
05092           else if (chromatogram.getChromatogramType() == ChromatogramSettings::SELECTED_REACTION_MONITORING_CHROMATOGRAM)
05093           {
05094             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1001473\" name=\"selected reaction monitoring chromatogram\" />\n";
05095           }
05096           else if (chromatogram.getChromatogramType() == ChromatogramSettings::ELECTROMAGNETIC_RADIATION_CHROMATOGRAM)
05097           {
05098             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000811\" name=\"electromagnetic radiation chromatogram\" />\n";
05099           }
05100           else if (chromatogram.getChromatogramType() == ChromatogramSettings::ABSORPTION_CHROMATOGRAM)
05101           {
05102             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000812\" name=\"absorption chromatogram\" />\n";
05103           }
05104           else if (chromatogram.getChromatogramType() == ChromatogramSettings::EMISSION_CHROMATOGRAM)
05105           {
05106             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000813\" name=\"emission chromatogram\" />\n";
05107           }
05108           else
05109           {
05110             // TODO
05111           }
05112           writePrecursor_(os, chromatogram.getPrecursor(), validator);
05113           writeProduct_(os, chromatogram.getProduct(), validator);
05114 
05115           //--------------------------------------------------------------------------------------------
05116           //binary data array list
05117           //--------------------------------------------------------------------------------------------
05118           String compression_term;
05119           if (options_.getCompression())
05120           {
05121             compression_term = "<cvParam cvRef=\"MS\" accession=\"MS:1000574\" name=\"zlib compression\" />";
05122           }
05123           else
05124           {
05125             compression_term = "<cvParam cvRef=\"MS\" accession=\"MS:1000576\" name=\"no compression\" />";
05126           }
05127           String encoded_string;
05128           os << "\t\t\t\t<binaryDataArrayList count=\"" << (2 + chromatogram.getFloatDataArrays().size() + chromatogram.getStringDataArrays().size() + chromatogram.getIntegerDataArrays().size()) << "\">\n";
05129           //write m/z array (default 64 bit precision)
05130           {
05131 
05132             if (options_.getMz32Bit())
05133             {
05134               std::vector<Real> data_to_encode(chromatogram.size());
05135               for (Size p = 0; p < chromatogram.size(); ++p)
05136                 data_to_encode[p] = chromatogram[p].getRT();
05137               decoder_.encode(data_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
05138               os << "\t\t\t\t\t<binaryDataArray encodedLength=\"" << encoded_string.size() << "\">\n";
05139               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000595\" name=\"time array\" unitAccession=\"UO:0000010\" unitName=\"second\" unitCvRef=\"MS\" />\n";
05140               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000521\" name=\"32-bit float\" />\n";
05141             }
05142             else
05143             {
05144               std::vector<DoubleReal> data_to_encode(chromatogram.size());
05145               for (Size p = 0; p < chromatogram.size(); ++p)
05146                 data_to_encode[p] = chromatogram[p].getRT();
05147               decoder_.encode(data_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
05148               os << "\t\t\t\t\t<binaryDataArray encodedLength=\"" << encoded_string.size() << "\">\n";
05149               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000595\" name=\"time array\" unitAccession=\"UO:0000010\" unitName=\"second\" unitCvRef=\"MS\" />\n";
05150               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000523\" name=\"64-bit float\" />\n";
05151             }
05152             os << "\t\t\t\t\t\t" << compression_term << "\n";
05153             os << "\t\t\t\t\t\t<binary>" << encoded_string << "</binary>\n";
05154             os << "\t\t\t\t\t</binaryDataArray>\n";
05155 
05156           }
05157           //write intensity array (default 32 bit precision)
05158           {
05159             if (options_.getIntensity32Bit())
05160             {
05161               std::vector<Real> data_to_encode(chromatogram.size());
05162               for (Size p = 0; p < chromatogram.size(); ++p)
05163                 data_to_encode[p] = chromatogram[p].getIntensity();
05164               decoder_.encode(data_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
05165               os << "\t\t\t\t\t<binaryDataArray encodedLength=\"" << encoded_string.size() << "\">\n";
05166               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000515\" name=\"intensity array\" unitAccession=\"MS:1000131\" unitName=\"number of counts\" unitCvRef=\"MS\"/>\n";
05167               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000521\" name=\"32-bit float\" />\n";
05168             }
05169             else
05170             {
05171               std::vector<DoubleReal> data_to_encode(chromatogram.size());
05172               for (Size p = 0; p < chromatogram.size(); ++p)
05173                 data_to_encode[p] = chromatogram[p].getIntensity();
05174               decoder_.encode(data_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
05175               os << "\t\t\t\t\t<binaryDataArray encodedLength=\"" << encoded_string.size() << "\">\n";
05176               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000515\" name=\"intensity array\" unitAccession=\"MS:1000131\" unitName=\"number of counts\" unitCvRef=\"MS\"/>\n";
05177               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000523\" name=\"64-bit float\" />\n";
05178             }
05179             os << "\t\t\t\t\t\t" << compression_term << "\n";
05180             os << "\t\t\t\t\t\t<binary>" << encoded_string << "</binary>\n";
05181             os << "\t\t\t\t\t</binaryDataArray>\n";
05182           }
05183           //write float data array
05184           for (Size m = 0; m < chromatogram.getFloatDataArrays().size(); ++m)
05185           {
05186             const typename ChromatogramType::FloatDataArray& array = chromatogram.getFloatDataArrays()[m];
05187             std::vector<DoubleReal> data64_to_encode(array.size());
05188             for (Size p = 0; p < array.size(); ++p)
05189               data64_to_encode[p] = array[p];
05190             decoder_.encode(data64_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
05191             String data_processing_ref_string = "";
05192             if (array.getDataProcessing().size() != 0)
05193             {
05194               data_processing_ref_string = String("dataProcessingRef=\"dp_sp_") + c + "_bi_" + m + "\"";
05195             }
05196             os << "\t\t\t\t\t<binaryDataArray arrayLength=\"" << array.size() << "\" encodedLength=\"" << encoded_string.size() << "\" " << data_processing_ref_string << ">\n";
05197             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000523\" name=\"64-bit float\" />\n";
05198             os << "\t\t\t\t\t\t" << compression_term << "\n";
05199             ControlledVocabulary::CVTerm bi_term = getChildWithName_("MS:1000513", array.getName());
05200             if (bi_term.id != "")
05201             {
05202               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"" << bi_term.id << "\" name=\"" << bi_term.name << "\" />\n";
05203             }
05204             else
05205             {
05206               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000786\" name=\"non-standard data array\" value=\"" << array.getName() << "\" />\n";
05207             }
05208             writeUserParam_(os, array, 6, "/mzML/run/chromatogramList/chromatogram/binaryDataArrayList/binaryDataArray/cvParam/@accession", validator);
05209             os << "\t\t\t\t\t\t<binary>" << encoded_string << "</binary>\n";
05210             os << "\t\t\t\t\t</binaryDataArray>\n";
05211           }
05212           //write integer data array
05213           for (Size m = 0; m < chromatogram.getIntegerDataArrays().size(); ++m)
05214           {
05215             const typename ChromatogramType::IntegerDataArray& array = chromatogram.getIntegerDataArrays()[m];
05216             std::vector<Int64> data64_to_encode(array.size());
05217             for (Size p = 0; p < array.size(); ++p)
05218               data64_to_encode[p] = array[p];
05219             decoder_.encodeIntegers(data64_to_encode, Base64::BYTEORDER_LITTLEENDIAN, encoded_string, options_.getCompression());
05220             String data_processing_ref_string = "";
05221             if (array.getDataProcessing().size() != 0)
05222             {
05223               data_processing_ref_string = String("dataProcessingRef=\"dp_sp_") + c + "_bi_" + m + "\"";
05224             }
05225             os << "\t\t\t\t\t<binaryDataArray arrayLength=\"" << array.size() << "\" encodedLength=\"" << encoded_string.size() << "\" " << data_processing_ref_string << ">\n";
05226             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000522\" name=\"64-bit integer\" />\n";
05227             os << "\t\t\t\t\t\t" << compression_term << "\n";
05228             ControlledVocabulary::CVTerm bi_term = getChildWithName_("MS:1000513", array.getName());
05229             if (bi_term.id != "")
05230             {
05231               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"" << bi_term.id << "\" name=\"" << bi_term.name << "\" />\n";
05232             }
05233             else
05234             {
05235               os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000786\" name=\"non-standard data array\" value=\"" << array.getName() << "\" />\n";
05236             }
05237             writeUserParam_(os, array, 6, "/mzML/run/chromatogramList/chromatogram/binaryDataArrayList/binaryDataArray/cvParam/@accession", validator);
05238             os << "\t\t\t\t\t\t<binary>" << encoded_string << "</binary>\n";
05239             os << "\t\t\t\t\t</binaryDataArray>\n";
05240           }
05241           //write string data arrays
05242           for (Size m = 0; m < chromatogram.getStringDataArrays().size(); ++m)
05243           {
05244             const typename ChromatogramType::StringDataArray& array = chromatogram.getStringDataArrays()[m];
05245             std::vector<String> data_to_encode;
05246             data_to_encode.resize(array.size());
05247             for (Size p = 0; p < array.size(); ++p)
05248               data_to_encode[p] = array[p];
05249             decoder_.encodeStrings(data_to_encode, encoded_string, options_.getCompression());
05250             String data_processing_ref_string = "";
05251             if (array.getDataProcessing().size() != 0)
05252             {
05253               data_processing_ref_string = String("dataProcessingRef=\"dp_sp_") + c + "_bi_" + m + "\"";
05254             }
05255             os << "\t\t\t\t\t<binaryDataArray arrayLength=\"" << array.size() << "\" encodedLength=\"" << encoded_string.size() << "\" " << data_processing_ref_string << ">\n";
05256             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1001479\" name=\"null-terminated ASCII string\" />\n";
05257             os << "\t\t\t\t\t\t" << compression_term << "\n";
05258             os << "\t\t\t\t\t\t<cvParam cvRef=\"MS\" accession=\"MS:1000786\" name=\"non-standard data array\" value=\"" << array.getName() << "\" />\n";
05259             writeUserParam_(os, array, 6, "/mzML/run/chromatogramList/chromatogram/binaryDataArrayList/binaryDataArray/cvParam/@accession", validator);
05260             os << "\t\t\t\t\t\t<binary>" << encoded_string << "</binary>\n";
05261             os << "\t\t\t\t\t</binaryDataArray>\n";
05262           }
05263           os << "\t\t\t\t</binaryDataArrayList>\n";
05264           os << "\t\t\t</chromatogram>" << "\n";
05265         }
05266 
05267 
05268         os << "    </chromatogramList>" << "\n";
05269       }
05270 
05271 
05272 
05273       os << "\t</run>\n";
05274 
05275       os << "</mzML>";
05276       logger_.endProgress();
05277     }
05278 
05279   } // namespace Internal
05280 } // namespace OpenMS
05281 
05282 #endif

OpenMS / TOPP release 1.10.0 Documentation generated on Thu Mar 7 2013 09:42:42 using doxygen 1.7.1