00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef OPENMS_APPLICATIONS_MAPALIGNERBASE_H
00036 #define OPENMS_APPLICATIONS_MAPALIGNERBASE_H
00037
00038 #include <OpenMS/FORMAT/MzMLFile.h>
00039 #include <OpenMS/FORMAT/ConsensusXMLFile.h>
00040 #include <OpenMS/FORMAT/FeatureXMLFile.h>
00041 #include <OpenMS/FORMAT/IdXMLFile.h>
00042 #include <OpenMS/FORMAT/FileHandler.h>
00043 #include <OpenMS/FORMAT/FileTypes.h>
00044 #include <OpenMS/FORMAT/TransformationXMLFile.h>
00045
00046 #include <OpenMS/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithm.h>
00047 #include <OpenMS/ANALYSIS/MAPMATCHING/MapAlignmentTransformer.h>
00048
00049 #include <OpenMS/APPLICATIONS/TOPPBase.h>
00050
00051 using namespace OpenMS;
00052 using namespace std;
00053
00054
00055
00056
00057
00064
00066
00067 class TOPPMapAlignerBase :
00068 public TOPPBase
00069 {
00070
00071 public:
00072 TOPPMapAlignerBase(String name, String description, bool official = true) :
00073 TOPPBase(name, description, official)
00074 {
00075 }
00076
00077
00078 static Param getModelDefaults(const String & default_model)
00079 {
00080 Param params;
00081 params.setValue("type", default_model, "Type of model");
00082
00083 StringList model_types = StringList::create("linear,b_spline,interpolated");
00084 if (!model_types.contains(default_model))
00085 {
00086 model_types.insert(model_types.begin(), default_model);
00087 }
00088 params.setValidStrings("type", model_types);
00089
00090 Param model_params;
00091 TransformationModelLinear::getDefaultParameters(model_params);
00092 params.insert("linear:", model_params);
00093 params.setSectionDescription("linear", "Parameters for 'linear' model");
00094 TransformationModelBSpline::getDefaultParameters(model_params);
00095 params.insert("b_spline:", model_params);
00096 params.setSectionDescription("b_spline", "Parameters for 'b_spline' model");
00097 TransformationModelInterpolated::getDefaultParameters(model_params);
00098
00099 const Param::ParamEntry & entry =
00100 model_params.getEntry("interpolation_type");
00101 StringList interpolation_types = entry.valid_strings;
00102 StringList::Iterator pos = find(interpolation_types.begin(),
00103 interpolation_types.end(), "polynomial");
00104 interpolation_types.erase(pos);
00105 model_params.setValidStrings("interpolation_type", interpolation_types);
00106 params.insert("interpolated:", model_params);
00107 params.setSectionDescription("interpolated",
00108 "Parameters for 'interpolated' model");
00109 return params;
00110 }
00111
00112 protected:
00113 void registerOptionsAndFlags_(const String & file_formats, const bool add_reference = false)
00114 {
00115 registerInputFileList_("in", "<files>", StringList(), "Input files separated by blanks (all must have the same file type)", true);
00116 setValidFormats_("in", StringList::create(file_formats));
00117 registerOutputFileList_("out", "<files>", StringList(), "Output files separated by blanks. Either 'out' or 'trafo_out' has to be provided. They can be used together.", false);
00118 setValidFormats_("out", StringList::create(file_formats));
00119 registerOutputFileList_("trafo_out", "<files>", StringList(), "Transformation output files separated by blanks. Either 'out' or 'trafo_out' has to be provided. They can be used together.", false);
00120 setValidFormats_("trafo_out", StringList::create("trafoXML"));
00121 addEmptyLine_();
00122 if (add_reference)
00123 {
00124 registerTOPPSubsection_("reference", "Options to define a reference file (use either 'file' or 'index', not both; if neither is given 'index' is used).");
00125 registerInputFile_("reference:file", "<file>", "", "File to use as reference (same file format as input files required)", false);
00126 setValidFormats_("reference:file", StringList::create(file_formats));
00127 registerIntOption_("reference:index", "<number>", 0, "Use one of the input files as reference ('1' for the first file, etc.).\nIf '0', no explicit reference is set - the algorithm will select a reference.", false);
00128 setMinInt_("reference:index", 0);
00129 }
00130 }
00131
00133 void handleReference_(MapAlignmentAlgorithm * alignment)
00134 {
00135
00136
00137
00138
00139
00140 Size reference_index = getIntOption_("reference:index");
00141 String reference_file = getStringOption_("reference:file");
00142 if (reference_index > getStringList_("in").size())
00143 {
00144 throw Exception::InvalidParameter(__FILE__, __LINE__, __PRETTY_FUNCTION__, "'reference:index' must not be higher than the number of input files");
00145 }
00146 if (reference_index && !reference_file.empty())
00147 {
00148 throw Exception::InvalidParameter(__FILE__, __LINE__, __PRETTY_FUNCTION__, "'reference:index' and 'reference:file' cannot be used together");
00149 }
00150
00151
00152 alignment->setReference(reference_index, reference_file);
00153 }
00154
00155 ExitCodes initialize_(MapAlignmentAlgorithm * alignment, bool check_ref = false)
00156 {
00157
00158
00159
00160 StringList ins = getStringList_("in");
00161 StringList outs = getStringList_("out");
00162 StringList trafos = getStringList_("trafo_out");
00163
00164
00165
00166
00167
00168 if (outs.empty() && trafos.empty())
00169 {
00170 writeLog_("Error: Either data output or transformation output files have to be provided!");
00171 return ILLEGAL_PARAMETERS;
00172 }
00173
00174 if (!outs.empty() && (ins.size() != outs.size()))
00175 {
00176 writeLog_("Error: The number of input and output files has to be equal!");
00177 return ILLEGAL_PARAMETERS;
00178 }
00179 if (!trafos.empty() && (ins.size() != trafos.size()))
00180 {
00181 writeLog_("Error: The number of input and transformation output files has to be equal!");
00182 return ILLEGAL_PARAMETERS;
00183 }
00184
00185 FileTypes::Type in_type = FileHandler::getType(ins[0]);
00186 for (Size i = 1; i < ins.size(); ++i)
00187 {
00188 if (FileHandler::getType(ins[i]) != in_type)
00189 {
00190 writeLog_("Error: All input files have to be in the same format!");
00191 return ILLEGAL_PARAMETERS;
00192 }
00193 }
00194
00195 if (check_ref)
00196 {
00197 Size reference_index = getIntOption_("reference:index");
00198 String reference_file = getStringOption_("reference:file");
00199 if (reference_index > getStringList_("in").size())
00200 {
00201 throw Exception::InvalidParameter(__FILE__, __LINE__, __PRETTY_FUNCTION__, "'reference:index' must not be higher than the number of input files");
00202 }
00203 if (reference_index && !reference_file.empty())
00204 {
00205 throw Exception::InvalidParameter(__FILE__, __LINE__, __PRETTY_FUNCTION__, "'reference:index' and 'reference:file' cannot be used together");
00206 }
00207
00208
00209 if (!reference_file.empty())
00210 {
00211 if (FileHandler::getType(reference_file) != in_type)
00212 {
00213 writeLog_("Error: Reference file has not the same format as other input files!");
00214 return ILLEGAL_PARAMETERS;
00215 }
00216 }
00217 }
00218
00219
00220
00221
00222 Param alignment_param = getParam_().copy("algorithm:", true);
00223
00224 writeDebug_("Used alignment parameters", alignment_param, 3);
00225 alignment->setParameters(alignment_param);
00226 alignment->setLogType(log_type_);
00227
00228 return EXECUTION_OK;
00229 }
00230
00232 ExitCodes commonMain_(MapAlignmentAlgorithm * alignment)
00233 {
00234 ExitCodes ret = initialize_(alignment);
00235 if (ret != EXECUTION_OK) return ret;
00236
00237 ProgressLogger progresslogger;
00238 progresslogger.setLogType(log_type_);
00239
00240
00241 StringList ins = getStringList_("in");
00242 StringList outs = getStringList_("out");
00243 StringList trafos = getStringList_("trafo_out");
00244 Param model_params = getParam_().copy("model:", true);
00245 String model_type = model_params.getValue("type");
00246 model_params = model_params.copy(model_type + ":", true);
00247 FileTypes::Type in_type = FileHandler::getType(ins[0]);
00248 std::vector<TransformationDescription> transformations;
00249
00250
00251
00252
00253 if (in_type == FileTypes::MZML)
00254 {
00255
00256 std::vector<MSExperiment<> > peak_maps(ins.size());
00257 MzMLFile f;
00258 f.setLogType(log_type_);
00259 for (Size i = 0; i < ins.size(); ++i)
00260 {
00261 f.load(ins[i], peak_maps[i]);
00262 }
00263
00264
00265 try
00266 {
00267 alignment->alignPeakMaps(peak_maps, transformations);
00268 }
00269 catch (Exception::NotImplemented &)
00270 {
00271 writeLog_("Error: The algorithm '" + alignment->getName() + "' cannot be used for peak data!");
00272 return INTERNAL_ERROR;
00273 }
00274 if (model_type != "none")
00275 {
00276 alignment->fitModel(model_type, model_params, transformations);
00277 }
00278 MapAlignmentTransformer::transformPeakMaps(peak_maps, transformations);
00279
00280
00281 progresslogger.startProgress(0, outs.size(), "writing output files");
00282 for (Size i = 0; i < outs.size(); ++i)
00283 {
00284 progresslogger.setProgress(i);
00285
00286
00287 addDataProcessing_(peak_maps[i], getProcessingInfo_(DataProcessing::ALIGNMENT));
00288
00289 f.store(outs[i], peak_maps[i]);
00290 }
00291 progresslogger.endProgress();
00292 }
00293
00294
00295
00296 else if (in_type == FileTypes::FEATUREXML)
00297 {
00298
00299 std::vector<std::vector<Peak2D> > feat_maps(ins.size());
00300 FeatureXMLFile f;
00301
00302 progresslogger.startProgress(0, ins.size(), "loading input files");
00303 for (Size i = 0; i < ins.size(); ++i)
00304 {
00305 progresslogger.setProgress(i);
00306 FeatureMap<> feature_map;
00307 f.load(ins[i], feature_map);
00308 feat_maps[i].resize(feature_map.size());
00309
00310 FeatureMap<>::const_iterator it = feature_map.begin();
00311 std::vector<Peak2D>::iterator c_it = feat_maps[i].begin();
00312 for (; it != feature_map.end(); ++it, ++c_it)
00313 {
00314 *c_it = reinterpret_cast<const Peak2D &>(*it);
00315 }
00316 }
00317 progresslogger.endProgress();
00318
00319
00320 try
00321 {
00322 alignment->alignCompactFeatureMaps(feat_maps, transformations);
00323 }
00324 catch (Exception::NotImplemented &)
00325 {
00326 writeLog_("Error: The algorithm '" + alignment->getName() + "' cannot be used for feature data!");
00327 return INTERNAL_ERROR;
00328 }
00329 if (model_type != "none")
00330 {
00331 alignment->fitModel(model_type, model_params, transformations);
00332 }
00333
00334
00335
00336 progresslogger.startProgress(0, outs.size(), "writing output files");
00337 for (Size i = 0; i < outs.size(); ++i)
00338 {
00339 progresslogger.setProgress(i);
00340
00341 FeatureMap<> feature_map;
00342 f.load(ins[i], feature_map);
00343
00344 MapAlignmentTransformer::transformSingleFeatureMap(feature_map, transformations[i]);
00345
00346
00347 addDataProcessing_(feature_map, getProcessingInfo_(DataProcessing::ALIGNMENT));
00348
00349 f.store(outs[i], feature_map);
00350 }
00351 progresslogger.endProgress();
00352 }
00353
00354
00355
00356 else if (in_type == FileTypes::CONSENSUSXML)
00357 {
00358
00359 std::vector<ConsensusMap> cons_maps(ins.size());
00360 ConsensusXMLFile f;
00361
00362 progresslogger.startProgress(0, ins.size(), "loading input files");
00363 for (Size i = 0; i < ins.size(); ++i)
00364 {
00365 progresslogger.setProgress(i);
00366 f.load(ins[i], cons_maps[i]);
00367 }
00368 progresslogger.endProgress();
00369
00370
00371 try
00372 {
00373 alignment->alignConsensusMaps(cons_maps, transformations);
00374 }
00375 catch (Exception::NotImplemented &)
00376 {
00377 writeLog_("Error: The algorithm '" + alignment->getName() + "' cannot be used for consensus feature data!");
00378 return INTERNAL_ERROR;
00379 }
00380 if (model_type != "none")
00381 {
00382 alignment->fitModel(model_type, model_params, transformations);
00383 }
00384 MapAlignmentTransformer::transformConsensusMaps(cons_maps, transformations);
00385
00386
00387 progresslogger.startProgress(0, outs.size(), "writing output files");
00388 for (Size i = 0; i < outs.size(); ++i)
00389 {
00390 progresslogger.setProgress(i);
00391
00392
00393 addDataProcessing_(cons_maps[i], getProcessingInfo_(DataProcessing::ALIGNMENT));
00394
00395 f.store(outs[i], cons_maps[i]);
00396 }
00397 progresslogger.endProgress();
00398 }
00399
00400
00401
00402 else if (in_type == FileTypes::IDXML)
00403 {
00404
00405 std::vector<std::vector<ProteinIdentification> > protein_ids_vec(ins.size());
00406 std::vector<std::vector<PeptideIdentification> > peptide_ids_vec(ins.size());
00407
00408 IdXMLFile f;
00409
00410
00411 progresslogger.startProgress(0, ins.size(), "loading input files");
00412 for (Size i = 0; i < ins.size(); ++i)
00413 {
00414 progresslogger.setProgress(i);
00415 f.load(ins[i], protein_ids_vec[i], peptide_ids_vec[i]);
00416 }
00417 progresslogger.endProgress();
00418
00419
00420 try
00421 {
00422 alignment->alignPeptideIdentifications(peptide_ids_vec, transformations);
00423 }
00424 catch (Exception::NotImplemented &)
00425 {
00426 writeLog_("Error: The algorithm '" + alignment->getName() + "' cannot be used for peptide data!");
00427 return INTERNAL_ERROR;
00428 }
00429 if (model_type != "none")
00430 {
00431 alignment->fitModel(model_type, model_params, transformations);
00432 }
00433 MapAlignmentTransformer::transformPeptideIdentifications(peptide_ids_vec,
00434 transformations);
00435
00436
00437 progresslogger.startProgress(0, outs.size(), "writing output files");
00438 for (Size i = 0; i < outs.size(); ++i)
00439 {
00440 progresslogger.setProgress(i);
00441 f.store(outs[i], protein_ids_vec[i], peptide_ids_vec[i]);
00442 }
00443 progresslogger.endProgress();
00444 }
00445 else
00446 {
00447
00448
00449 return ILLEGAL_PARAMETERS;
00450 }
00451
00452 if (!trafos.empty())
00453 {
00454 for (Size i = 0; i < transformations.size(); ++i)
00455 {
00456 TransformationXMLFile().store(trafos[i], transformations[i]);
00457 }
00458 }
00459
00460 return EXECUTION_OK;
00461 }
00462
00463 };
00464
00466
00467 #endif // OPENMS_APPLICATIONS_MAPALIGNERBASE_H