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

ANDIHandler.h (Maintainer: Marc Sturm)

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // --------------------------------------------------------------------------
00005 //                   OpenMS Mass Spectrometry Framework
00006 // --------------------------------------------------------------------------
00007 //  Copyright (C) 2003-2008 -- Oliver Kohlbacher, Knut Reinert
00008 //
00009 //  This library is free software; you can redistribute it and/or
00010 //  modify it under the terms of the GNU Lesser General Public
00011 //  License as published by the Free Software Foundation; either
00012 //  version 2.1 of the License, or (at your option) any later version.
00013 //
00014 //  This library is distributed in the hope that it will be useful,
00015 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 //  Lesser General Public License for more details.
00018 //
00019 //  You should have received a copy of the GNU Lesser General Public
00020 //  License along with this library; if not, write to the Free Software
00021 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // --------------------------------------------------------------------------
00024 // $Maintainer: Marc Sturm $
00025 // --------------------------------------------------------------------------
00026 
00027 #ifndef OPENMS_FORMAT_HANDLERS_ANDIHANDLER_H
00028 #define OPENMS_FORMAT_HANDLERS_ANDIHANDLER_H
00029 
00030 #include <netcdf.h>
00031 #include <ms10.h>
00032 #include <fstream>
00033 #include <sstream>
00034 
00035 #include <OpenMS/CONCEPT/Exception.h>
00036 #include <OpenMS/KERNEL/MSExperiment.h>
00037 #include <OpenMS/CONCEPT/ProgressLogger.h>
00038 
00039 namespace OpenMS
00040 {
00041   namespace Internal
00042   {
00050     template <typename MapType>
00051     class ANDIHandler
00052     {
00053       public:
00056 
00057         ANDIHandler(MapType& exp, const ProgressLogger& logger)
00058         : exp_(exp),
00059           pol_(),
00060           logger_(logger)
00061         {
00062           MetaInfoRegistry& registry =  MetaInfo().registry();
00063           for (int i=0; i<NUM_PARAM; i++) 
00064           {
00065             registry.registerName(user_params_[i], description_[i]);
00066           }
00067         }
00069         virtual ~ANDIHandler()
00070         {
00071         }
00073 
00075         void parse(std::string file_name);
00076 
00077       protected:
00080 
00081         void getAdminData_(MS_Admin_Data* admin_data);
00082     
00084         void getSampleData_(MS_Sample_Data* sample_data);
00085     
00087         void getTestData_(MS_Test_Data* test_data);
00088     
00090         void getInstrumentData_(MS_Instrument_Data* inst_data);
00091     
00093         void getRawPerScan_(MS_Raw_Per_Scan* scan_data, MS_Raw_Data_Global* global_data);
00095     
00097         MapType& exp_;    
00099         IonSource::Polarity pol_;
00100     
00103 
00104         enum userParamsID {CONTACT=0, PROC, ANDI_ERROR, CALHIST, CALTIMES,
00105                           INSTSERIAL, INSTCOMMENTS, INSTSOFTWARE, INSTFIRMWARE,
00106                           INSTOS, INSTID, INLETTEMP, IONMODEADD, SRCTEMP, ACCPOT,
00107                           INSTPARAMS, DETPOT, DETENTRPOT, NUM_PARAM};
00109         static const std::string user_params_[];
00111         static const std::string description_[];
00113     
00115         inline String string_(char* input)
00116         {
00117           return (input == NULL)? "" : String(input);
00118         }
00119     
00125         inline float float_(float input, float def=0.0f)
00126         {
00127           return (input < -1000)? def : input;
00128         }
00129     
00135         inline int int_(int input, int def=0)
00136         {
00137           return (input < -1000)? def : input;
00138         }
00139         
00141         const ProgressLogger& logger_;
00142   };
00143 
00144   //---------------------------------------------------------------------------
00145 
00146   template <typename MapType>
00147   const std::string ANDIHandler<MapType>::user_params_[] = {"ContactPosition",
00148       "ProcessingNumer", "ErrorLog", "CalibrationHistory", "NumOfCalibrations",
00149       "InstSerial", "InstComments", "InstSoftware", "InstFirmware", "InstOS", "InstID",
00150       "InletTemp", "IonModeAdd", "SrcTemp", "AccPot", "InstParams", "DetPot", "DetEntrPot"};
00151 
00152   template <typename MapType>
00153   const std::string ANDIHandler<MapType>::description_[] = {"Position of the contact person",
00154       "number of times processed", "Processing Method error log", "history of calibration",
00155       "number of times calibrated", "Instrument serial number", "Instrument id comments",
00156       "Instrument software revision", "Instrument firmware revision",
00157       "Operating system revision", "Instrument ProteinIdentification code",
00158       "Spectrometer inlet temperature", "Additional ionization mode information",
00159       "Ionization source temperature", "Accelerating Potential",
00160       "Instrument parameter comments", "Detector potential", "Detector entrance potential"};
00161 
00162   template <typename MapType>
00163   void ANDIHandler<MapType>::parse(std::string file)
00164   {
00165     if (file=="") return;
00166    
00167     char* file_name = (char*) file.c_str();
00168     
00169     std::ifstream infile(file_name);
00170     if (!infile)
00171     {
00172       throw Exception::FileNotFound(__FILE__, __LINE__, __PRETTY_FUNCTION__,file_name);
00173     }
00174     infile.close();
00175 
00176     ncopts = 0;  // Disable automatic error-abort of netcdf
00177     int file_id = ms_open_read(file_name);
00178     
00179     MS_Admin_Data      ms_admin;
00180     MS_Sample_Data     ms_sample;
00181     MS_Test_Data       ms_test;
00182     MS_Raw_Data_Global ms_raw_global;
00183     MS_Instrument_Data ms_inst;
00184     
00185     if (file_id == MS_ERROR)
00186     {
00187       throw Exception::ParseError(__FILE__, __LINE__, __PRETTY_FUNCTION__,file_name,"Error: could not open ANDI/MS file. Invalid file!");
00188     }
00189     
00190     ms_init_global( 0, &ms_admin, &ms_sample, &ms_test, &ms_raw_global);
00191     
00192     if (ms_read_global( file_id, &ms_admin, &ms_sample, &ms_test, &ms_raw_global) == MS_ERROR) 
00193     {
00194       throw Exception::ParseError(__FILE__, __LINE__, __PRETTY_FUNCTION__,file_name,"Error: could not read global data of ANDI/MS file. Invalid file!");
00195     }
00196     
00197     // Global Data
00198     getAdminData_(&ms_admin);
00199     getSampleData_(&ms_sample);
00200     getTestData_(&ms_test);
00201 
00202     long index;
00203     long num_scans = ms_raw_global.nscans;
00204     logger_.startProgress(0,num_scans,"reading ANDI/MS file");
00205     exp_.reserve(num_scans);
00206     long num_inst = ms_admin.number_instrument_components;
00207     ms_admin_expt_t expt_type = ms_admin.experiment_type;
00208     bool is_library = (expt_library == expt_type );
00209     
00210     ms_init_instrument(0,&ms_inst);
00211     if (num_inst > 1) num_inst = 1; // Read only the first instrument
00212     for (index = 0; index < num_inst; index++)
00213     {
00214       logger_.setProgress(index);
00215       ms_inst.inst_no = index;
00216 
00217       if (ms_read_instrument( file_id, &ms_inst) == MS_ERROR)
00218       {
00219         std::cerr << "Warning: could not read instrument data of ANDI/MS file '" << file <<"'." << std::endl;
00220       }
00221       else
00222       {
00223         //read data
00224         getInstrumentData_(&ms_inst);
00225       }
00226       //clean up
00227       ms_init_instrument(1,&ms_inst);
00228     }
00229     MS_Raw_Per_Scan    ms_raw;
00230     MS_Raw_Library     ms_lib;
00231 
00232     int err_code;
00233     
00234     ms_init_per_scan(0, &ms_raw, &ms_lib);
00235     
00236     for (index=0; index<num_scans; index++) 
00237     {
00238       ms_raw.scan_no = index;
00239 
00240       if (is_library)
00241       {
00242         ms_lib.scan_no = index;
00243         err_code = ms_read_per_scan(file_id, &ms_raw, &ms_lib);
00244       }
00245       else  
00246       {
00247         err_code = ms_read_per_scan(file_id, &ms_raw, NULL);
00248       }
00249       
00250       if (err_code == MS_ERROR)
00251       {
00252         std::cerr << "Warning: could not read scan " << index << " of ANDI/MS file '" << file << "'." << std::endl;
00253       }
00254       else
00255       {
00256         //parse data
00257         getRawPerScan_(&ms_raw,&ms_raw_global);
00258       } 
00259       //clean up
00260       ms_init_per_scan( 1, &ms_raw, &ms_lib);         
00261     }
00262 
00263     ms_init_global( 1, &ms_admin, &ms_sample, &ms_test, &ms_raw_global);
00264     ms_close( file_id);
00265     logger_.endProgress();
00266   }
00267 
00268   template <typename MapType>
00269   void ANDIHandler<MapType>::getAdminData_(MS_Admin_Data* admin_data)
00270   {
00271     // Partition file reference into name and path
00272     std::string file = string_(admin_data->source_file_reference);
00273     int last_slash = file.rfind("/",file.size());
00274     int last_backslash = file.rfind("\\",file.size());
00275     int cut = (last_slash > last_backslash)? last_slash : last_backslash;
00276     exp_.getSourceFile().setNameOfFile( file.substr(cut+1) ); 
00277     exp_.getSourceFile().setPathToFile( file.substr(0,cut+1) ); 
00278 
00279     exp_.getSourceFile().setFileType( string_(admin_data->source_file_format) );
00280 
00281     ContactPerson contact;
00282     contact.setLastName( string_(admin_data->operator_name) );
00283     contact.setMetaValue(user_params_[CONTACT], String("Operator"));
00284     exp_.getContacts().push_back(contact);
00285 
00286     
00287     contact = ContactPerson();
00288     contact.setLastName( string_(admin_data->dataset_owner) );
00289     contact.setContactInfo( string_(admin_data->dataset_origin) );
00290     contact.setMetaValue(user_params_[CONTACT], String("Dataset owner"));
00291     exp_.getContacts().push_back(contact);
00292     
00293     typedef ProcessingMethod pm;
00294     // Centroided Mass Spectrum, Continuum Mass Spectrum, Library Mass Spectrum
00295     int exp_map[] = {SpectrumSettings::PEAKS, SpectrumSettings::RAWDATA, 0};
00296     exp_.getProcessingMethod().setSpectrumType( (SpectrumSettings::SpectrumType) exp_map[admin_data->experiment_type - expt_centroid]);
00297 
00298     exp_.getSoftware().setName( string_(admin_data->post_expt_program_name) );
00299     exp_.getProcessingMethod().setMetaValue(user_params_[ANDI_ERROR], string_(admin_data->error_log));
00300     exp_.getProcessingMethod().setMetaValue(user_params_[PROC], int_(admin_data->number_times_processed));
00301    
00302     std::stringstream buffer;
00303     buffer << string_(admin_data->calibration_history_0) << string_(admin_data->calibration_history_1)
00304            << string_(admin_data->calibration_history_2) << string_(admin_data->calibration_history_3);
00305     exp_.getProcessingMethod().setMetaValue(user_params_[CALHIST], String(buffer.str())); 
00306     exp_.getProcessingMethod().setMetaValue(user_params_[CALTIMES], int_(admin_data->number_times_calibrated)); 
00307 
00308     // unused MS_Admin_Data fields: comments, experiment_title, ms_template_revision, netcdf_revision, languages
00309     // experiment_date_time, netcdf_date_time, source_file_date_time, pre_expt_program_name
00310     // experiment_x_ref_0,  experiment_x_ref_1, experiment_x_ref_2, experiment_x_ref_3, external_file_ref_0
00311     // external_file_ref_1, external_file_ref_2, external_file_ref_3
00312   }
00313 
00314 
00315   template <typename MapType>
00316   void ANDIHandler<MapType>::getSampleData_(MS_Sample_Data* sample_data)
00317   {
00318     std::stringstream buffer;
00319     if (sample_data->internal_id != NULL) buffer << sample_data->internal_id;
00320     if (sample_data->external_id != NULL) buffer << "(" << sample_data->external_id << ")";
00321     exp_.getSample().setNumber(buffer.str());
00322     exp_.getSample().setComment( string_(sample_data->comments) );
00323 
00324     // Solid, Liquid, Gas, Supercritical Fluid, Plasma, Other
00325     int sample_map[] = {Sample::SOLID, Sample::LIQUID, Sample::GAS, 0, 0, 0, 0};
00326     exp_.getSample().setState( (Sample::SampleState) sample_map[sample_data->state - state_solid]);
00327 
00328     // unused sample_data fields: owner, receipt_date_time, procedure_name, prep_procedure, matrix, storage
00329     // disposal, history, manual_handling, prep_comments
00330   }
00331 
00332   template <typename MapType>
00333   void ANDIHandler<MapType>::getTestData_(MS_Test_Data* test_data)
00334   {
00335     exp_.getInstrument().setMetaValue(user_params_[INSTPARAMS], string_(test_data->comments));
00336 
00337 
00338     // Membrane Separator, Capillary Direct, Open Split, Jet Separator, Direct Inlet Probe, Septum, Particle Beam,
00339     // Reservoir, Moving Belt, Atmospheric Pressure Chemical Ionization, Flow Injection Analysis, Electrospray,
00340     // Infusion, Thermospray, Other Probe, Other
00341     typedef IonSource is;
00342     IonSource& src = exp_.getInstrument().getIonSource();
00343     int inlet_map[] = {is::MEMBRANESEPARATOR, 0, is::OPENSPLIT, is::JETSEPARATOR, is::DIRECT, is::SEPTUM,
00344     is::PARTICLEBEAM, is::RESERVOIR, is::MOVINGBELT, 0, is::FLOWINJECTIONANALYSIS, is::ELECTROSPRAYINLET,
00345     is::INFUSION, is::THERMOSPRAYINLET, 0, 0};
00346     src.setInletType( (is::InletType) inlet_map[test_data->ms_inlet - inlet_membrane]);
00347     src.setMetaValue(user_params_[INLETTEMP], float_(test_data->ms_inlet_temperature));
00348 
00349     // Electron Impact, Chemical Ionization, Fast Atom Bombardment, Field Desorption, Field Ionization,
00350     // Electrospray, Thermospray, Atmospheric Pressure Chemical Ionization, Plasma Desorption,
00351     // Laser Desorption, Spark Ionization, Thermal Ionization, Other
00352     int ion_map[] = {is::EI, is::CI, is::FAB, is::FD, is::FI, is::ESI, 
00353                      is::TSP, is::APCI, is::PD, is::LD, is::SI, is::TI, 0};
00354     src.setIonizationMethod( (is::IonizationMethod) ion_map[test_data->ionization_mode - ionization_ei]);
00355 
00356     std::stringstream buffer;
00357     if (test_data->fab_type != NULL) buffer << "FABType=" << test_data->fab_type << " ";
00358     if (test_data->fab_matrix != NULL) buffer << "FABMatrix=" << test_data->fab_matrix << " ";
00359     if (test_data->reagent_gas != NULL) buffer << "ReagentGas=" << test_data->reagent_gas << " ";
00360     buffer << "ReagentGasPressure=" << test_data->reagent_gas_pressure << " ";
00361     buffer << "ElectronEnergy=" << test_data->electron_energy << " ";
00362     buffer << "LaserWaveLength=" << test_data->laser_wavelength << " ";
00363     buffer << "FilamentCurrent=" << test_data->filament_current << " ";
00364     buffer << "EmissionCurrent=" << test_data->emission_current << " ";
00365     src.setMetaValue(user_params_[IONMODEADD], String(buffer.str()));
00366     src.setMetaValue(user_params_[SRCTEMP], test_data->source_temperature);
00367     src.setMetaValue(user_params_[ACCPOT], test_data->accelerating_potential);
00368 
00369     pol_ = (IonSource::Polarity) (test_data->ionization_polarity - polarity_plus + 1);
00370 
00371     // Electron Multiplier, Photomultplier, Focal Plane Array, Faraday Cup, Conversion Dynode Electron Multiplier,
00372     // Conversion dynode Photomultiplier, Multicollector, Other
00373     typedef IonDetector id;
00374     IonDetector& det = exp_.getInstrument().getIonDetector();
00375     int detector_map[] = {id::ELECTRONMULTIPLIER, id::PHOTOMULTIPLIER, id::FOCALPLANEARRAY, id::FARADAYCUP,
00376                           id::CONVERSIONDYNODEELECTRONMULTIPLIER, id::CONVERSIONDYNODEPHOTOMULTIPLIER,
00377                           id::MULTICOLLECTOR, 0};
00378     det.setType( (id::Type) detector_map[test_data->detector_type - detector_em]);
00379     det.setMetaValue(user_params_[DETPOT], float_(test_data->detector_potential));
00380     det.setMetaValue(user_params_[DETENTRPOT], float_(test_data->detector_entrance_potential));
00381 
00382 
00383 
00384     typedef MassAnalyzer ma;
00385     ma analyzer;
00386 
00387     int dir_map[] = {ma::UP, ma::DOWN, 0};
00388     analyzer.setScanDirection( (ma::ScanDirection) dir_map[test_data->scan_direction - direction_up]);
00389     
00390     // Linear, Exponential, Quadratic,  Other
00391     int law_map[] = {ma::LINEAR, ma::EXPONENTIAL, ma::QUADRATIC, 0};
00392     analyzer.setScanLaw( (ma::ScanLaw) law_map[test_data->scan_law - law_linear]);
00393 
00394     //Mass Scan, Selected Ion Detection, Other
00395     int function_map[] = {ma::MASSSCAN, ma::SELECTEDIONDETECTION, 0};
00396     analyzer.setScanFunction( (ma::ScanFunction) function_map[test_data->scan_function - function_scan]);
00397 
00398     analyzer.setResolutionType( (ma::ResolutionType) (test_data->resolution_type - resolution_constant));
00399     analyzer.setScanTime(test_data->scan_time);
00400 
00401     if (test_data->resolution_method != NULL)
00402     {
00403       if (String(test_data->resolution_method) == "50% peak height")
00404       {
00405         analyzer.setResolutionMethod(ma::FWHM);
00406       }
00407       else
00408       {
00409         if (String(test_data->resolution_method) == "10% peak valley") 
00410         {
00411           analyzer.setResolutionMethod(ma::TENPERCENTVALLEY);
00412         }
00413       }
00414     }
00415     exp_.getInstrument().getMassAnalyzers().push_back(analyzer);
00416 
00417     // unused MS_Test_Data fields: mass_calibration_file, external_reference_file, internal_reference_file
00418     // test_data->separation_type
00419   }
00420 
00421   template <typename MapType>
00422   void ANDIHandler<MapType>::getInstrumentData_(MS_Instrument_Data* inst_data)
00423   {
00424     exp_.getInstrument().setName( string_(inst_data->name) );
00425     exp_.getInstrument().setVendor( string_(inst_data->manufacturer) );
00426     exp_.getInstrument().setModel( string_(inst_data->model_number) );
00427 
00428     exp_.getInstrument().setMetaValue(user_params_[INSTSERIAL], string_(inst_data->serial_number));
00429     exp_.getInstrument().setMetaValue(user_params_[INSTCOMMENTS], string_(inst_data->comments));
00430     exp_.getInstrument().setMetaValue(user_params_[INSTSOFTWARE], string_(inst_data->software_version));
00431     exp_.getInstrument().setMetaValue(user_params_[INSTFIRMWARE], string_(inst_data->firmware_version));
00432     exp_.getInstrument().setMetaValue(user_params_[INSTOS], string_(inst_data->operating_system));
00433     exp_.getInstrument().setMetaValue(user_params_[INSTID], string_(inst_data->id));
00434   }
00435 
00436   template <typename MapType>
00437   void ANDIHandler<MapType>::getRawPerScan_(MS_Raw_Per_Scan* scan_data, MS_Raw_Data_Global* global_data)
00438   {
00439     float mass_factor = float_(global_data->mass_factor, 1.0f);
00440     float intens_factor = float_(global_data->intensity_factor, 1.0f);
00441     float intens_offset = float_(global_data->intensity_offset);
00442 
00443     // in case anyone set the factor accidentally to zero -> avoid all zero values
00444     if (mass_factor==0.0f) mass_factor = 1.0f;
00445     if (intens_factor==0.0f) intens_factor = 1.0f;
00446     
00447     //Abort if no masses are present or if times are stored in this scan
00448     if (global_data->has_masses!=1 || global_data->has_times==1)
00449     {
00450       return;
00451     }
00452     
00453     //resize experiment
00454     exp_.resize(exp_.size()+1);
00455     
00456     //set scan data (besides peaks)
00457     typename MapType::SpectrumType& spectrum = exp_.back();
00458     spectrum.resize(scan_data->points);
00459     spectrum.setRT( float_(scan_data->scan_acq_time));
00460     spectrum.setMSLevel(1);
00461     spectrum.getInstrumentSettings().setMzRangeStart(float_(scan_data->mass_range_min));
00462     spectrum.getInstrumentSettings().setMzRangeStop(float_(scan_data->mass_range_max));
00463     spectrum.getInstrumentSettings().setPolarity(pol_);
00464 
00465     //check intensity/mass format
00466     std::string intensity_format = ms_enum_to_string(global_data->intensity_format);
00467     if (intensity_format!= "Short" && intensity_format!= "Long" && intensity_format!= "Float" && intensity_format!= "Double")
00468     {
00469       throw Exception::ParseError(__FILE__, __LINE__, __PRETTY_FUNCTION__,"","ANDI/MS file parse error. Unknown intensity format '"+intensity_format+"'.");
00470     }
00471     std::string mass_format = ms_enum_to_string(global_data->mass_format);
00472     if (mass_format!= "Short" && mass_format!= "Long" && mass_format!= "Float" && mass_format!= "Double")
00473     {
00474       throw Exception::ParseError(__FILE__, __LINE__, __PRETTY_FUNCTION__,"", "ANDI/MS file parse error. Unknown mass format '"+mass_format+"'.");
00475     }
00476     
00477     //load peak data
00478     for (int i=0; i < scan_data->points; i++)
00479     {
00480       //parse intensity
00481       double intensity(0);
00482       if (intensity_format == "Short") intensity =  (double) ((short*)  scan_data->intensities)[i];
00483       else if (intensity_format == "Long") intensity =  (double) ((long*)   scan_data->intensities)[i];
00484       else if (intensity_format == "Float") intensity =  (double) ((float*)  scan_data->intensities)[i];
00485       else if (intensity_format == "Double") intensity =  ((double*) scan_data->intensities)[i];
00486       spectrum.getContainer()[i].setIntensity(intensity * intens_factor + intens_offset);
00487       
00488       //parse mass
00489       double mass(0);
00490       if (mass_format == "Short") mass = (double) ((short*)  scan_data->masses)[i];
00491       else if (mass_format == "Long") mass = (double) ((long*)   scan_data->masses)[i];
00492       else if (mass_format == "Float") mass = (double) ((float*)  scan_data->masses)[i];
00493       else if (mass_format == "Double") mass = ((double*) scan_data->masses)[i];
00494       spectrum.getContainer()[i].setPosition(mass * mass_factor);
00495     }
00496 
00497     // unused MS_Raw_Data_Global fields:  mass_axis_global_min, mass_axis_global_max, time_axis_global_min,
00498     // time_axis_global_max, intensity_axis_global_min, intensity_axis_global_max, calibrated_mass_min);
00499     // calibrated_mass_max, uniform_flag, mass_label, time_label, intensity_label,
00500     // mass_units, time_units, intensity_units, total_intensity_units
00501 
00502     // unused MS_Raw_Per_Scan fields: flags, a_d_rate, a_d_coadditions, scan_duration, time_range_min,
00503     // time_range_max, inter_scan_time, resolution, actual_scan_no
00504   }
00505 
00506   } // namespace Internal
00507 } // namespace OpenMS
00508 
00509 #endif

Generated Tue Apr 1 15:36:32 2008 -- using doxygen 1.5.4 OpenMS / TOPP 1.1