diff --git a/.gitpod.yml b/.gitpod.yml index 20cff31c20f..09f3121f30b 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,12 +1,15 @@ tasks: - - init: cp -r .vscode-gitpod .vscode && echo "Welcome!" - prebuild: git config -f .gitmodules submodule.THIRDPARTY.shallow true && - git submodule update --init THIRDPARTY && - export PATH=$PATH$( find ${PWD}/THIRDPARTY/All -type d -printf ":%p" ) && - export PATH=$PATH$( find ${PWD}/THIRDPARTY/Linux/64bit -type d -printf ":%p" ) && - mkdir -p build && pushd build && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_PREFIX_PATH='/contrib-build/;/usr/;/usr/local' -DBOOST_USE_STATIC=OFF ../ && make -j16 && popd - command: export PATH=$PATH$( find ${PWD}/THIRDPARTY/All -type d -printf ":%p" ) && - export PATH=$PATH$( find ${PWD}/THIRDPARTY/Linux/64bit -type d -printf ":%p" ) + - init: > + cp -r .vscode-gitpod .vscode && echo "Welcome!" + git config -f .gitmodules submodule.THIRDPARTY.shallow true && + git submodule update --init THIRDPARTY && + export PATH=$PATH$( find ${PWD}/THIRDPARTY/All -type d -printf ":%p" ) && + export PATH=$PATH$( find ${PWD}/THIRDPARTY/Linux/64bit -type d -printf ":%p" ) && + mkdir -p build && pushd build && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_PREFIX_PATH='/contrib-build/;/usr/;/usr/local' -DBOOST_USE_STATIC=OFF ../ && + make -j16 && popd + command: > + export PATH=$PATH$( find ${PWD}/THIRDPARTY/All -type d -printf ":%p" ) && + export PATH=$PATH$( find ${PWD}/THIRDPARTY/Linux/64bit -type d -printf ":%p" ) image: file: .gitpod.Dockerfile github: @@ -37,4 +40,4 @@ vscode: - cschlosser.doxdocgen@0.7.2:g0DIKlW09t+j2Xi04fzrAA== - hbenl.vscode-test-explorer@2.19.2:8rKHUShFJJd0UivektEkng== - fredericbonnet.cmake-test-adapter@0.10.0:Fb9mp0fAtp8s6LKtpzJAyw== - - notskm.clang-tidy@0.5.1:+QMYmPGGWj0QCN6sba42Vw== \ No newline at end of file + - notskm.clang-tidy@0.5.1:+QMYmPGGWj0QCN6sba42Vw== diff --git a/AUTHORS b/AUTHORS index 0bfb4d827f3..716b461465a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -21,6 +21,7 @@ the authors tag in the respective file header. - Daniel Jameson - Darren Kessner - David Wojnar + - David Voigt - Dilek Dere - Dimitri Schachmann - Dominik Schmitz diff --git a/CHANGELOG b/CHANGELOG index d12d0c2914c..561e50dc2f4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,7 @@ Adapters/Third-party support: - Added basic Triqler export - ParamEditor with more convenient StringList editing (#5135) - TOPPAS: add a `recent files` submenu +- removed InspectAdapter Further fixes: - support for GLPK 5.x (#5127) diff --git a/README.md b/README.md index 903821da29f..7f2281b0eaa 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ OpenMS [![Codacy Badge](https://api.codacy.com/project/badge/Grade/93e71bad214f46d2a534ec92dbc2efc9)](https://www.codacy.com/app/OpenMS/OpenMS?utm_source=github.com&utm_medium=referral&utm_content=OpenMS/OpenMS&utm_campaign=badger) [![Build Status](https://travis-ci.org/OpenMS/OpenMS.svg?branch=develop)](https://travis-ci.org/OpenMS/OpenMS) [![Project Stats](https://www.openhub.net/p/open-ms/widgets/project_thin_badge.gif)](https://www.openhub.net/p/open-ms) +![Discord Shield](https://discordapp.com/api/guilds/832282841836159006/widget.png?style=shield) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/OpenMS/OpenMS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![install with bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg?style=flat-square)](http://bioconda.github.io/recipes/openms-meta/README.html) [![documentation](https://codedocs.xyz/doxygen/doxygen.svg)](https://abibuilder.informatik.uni-tuebingen.de/archive/openms/Documentation/release/latest/html/index.html) @@ -38,7 +39,7 @@ Berlin, and the ETH Zürich. Features -------- -- Core C++ library under three-clause BSD licence using modern C++11 +- Core C++ library under three-clause BSD licence using modern C++17 - Python bindings to the C++ API through pyOpenMS - Major community file formats supported (mzML, mzXML, mzIdentXML, pepXML etc) - Over 150+ individual analysis tools (TOPP Tools), covering most MS and LC-MS data processing and mining tasks diff --git a/doc/code_examples/Tutorial_Param.cpp b/doc/code_examples/Tutorial_Param.cpp index 83ba115e33b..3e04f98d9a8 100644 --- a/doc/code_examples/Tutorial_Param.cpp +++ b/doc/code_examples/Tutorial_Param.cpp @@ -28,6 +28,7 @@ // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#include #include #include @@ -43,7 +44,7 @@ Int main() param.setValue("file:data:min_int", 0); param.setValue("file:data:max_int", 16459); - cout << "Name : " << (String)(param.getValue("file:name")) << endl; + cout << "Name : " << (string)(param.getValue("file:name")) << endl; cout << "Size : " << (float)(param.getValue("file:size(MB)")) << endl; cout << "Min int: " << (UInt)(param.getValue("file:data:min_int")) << endl; cout << "Max int: " << (UInt)(param.getValue("file:data:max_int")) << endl; diff --git a/doc/doxygen/parameters/DefaultParamHandlerDocumenter.cpp b/doc/doxygen/parameters/DefaultParamHandlerDocumenter.cpp index d4e995e9e97..b7229abf31f 100644 --- a/doc/doxygen/parameters/DefaultParamHandlerDocumenter.cpp +++ b/doc/doxygen/parameters/DefaultParamHandlerDocumenter.cpp @@ -189,18 +189,22 @@ void writeParameters(const String& class_name, const Param& param, bool table_on ofstream f((String("output/OpenMS_") + class_name + ".parameters").c_str()); if (!table_only) + { f << "Parameters of this class are:

\n"; + } f << "" << endl; f << "" << endl; String type, description, restrictions; for (Param::ParamIterator it = param.begin(); it != param.end(); ++it) { restrictions = ""; - if (it->value.valueType() == DataValue::INT_VALUE || it->value.valueType() == DataValue::INT_LIST) + if (it->value.valueType() == ParamValue::INT_VALUE || it->value.valueType() == ParamValue::INT_LIST) { type = "int"; - if (it->value.valueType() == DataValue::INT_LIST) + if (it->value.valueType() == ParamValue::INT_LIST) + { type += " list"; + } //restrictions bool first = true; @@ -212,14 +216,16 @@ void writeParameters(const String& class_name, const Param& param, bool table_on if (it->max_int != (numeric_limits::max)()) { if (!first) + { restrictions += ' '; + } restrictions += String("max: ") + it->max_int; } } - else if (it->value.valueType() == DataValue::DOUBLE_VALUE || it->value.valueType() == DataValue::DOUBLE_LIST) + else if (it->value.valueType() == ParamValue::DOUBLE_VALUE || it->value.valueType() == ParamValue::DOUBLE_LIST) { type = "float"; - if (it->value.valueType() == DataValue::DOUBLE_LIST) + if (it->value.valueType() == ParamValue::DOUBLE_LIST) type += " list"; //restrictions @@ -236,10 +242,10 @@ void writeParameters(const String& class_name, const Param& param, bool table_on restrictions += String("max: ") + it->max_float; } } - else if (it->value.valueType() == DataValue::STRING_VALUE || it->value.valueType() == DataValue::STRING_LIST) + else if (it->value.valueType() == ParamValue::STRING_VALUE || it->value.valueType() == ParamValue::STRING_LIST) { type = "string"; - if (it->value.valueType() == DataValue::STRING_LIST) + if (it->value.valueType() == ParamValue::STRING_LIST) type += " list"; //restrictions @@ -289,7 +295,7 @@ void writeParameters(const String& class_name, const Param& param, bool table_on } //replace # and @ in values - String value = it->value; + String value = it->value.toString(true); value.substitute("@", "XXnot_containedXX"); value.substitute("XXnot_containedXX", "@@"); value.substitute("#", "XXnot_containedXX"); @@ -480,7 +486,7 @@ int main(int argc, char** argv) // some classes require a QApplication QApplication app(argc, argv); - DOCME(TOPPViewBase); + DOCME2(TOPPViewBase, TOPPViewBase(TOPPViewBase::TOOL_SCAN::SKIP_SCAN)); DOCME(TOPPASBase); DOCME2(Plot1DCanvas, Plot1DCanvas(Param(), nullptr)); diff --git a/doc/doxygen/parameters/TOPPDocumenter.cpp b/doc/doxygen/parameters/TOPPDocumenter.cpp index 441d107d8b1..779719e185d 100644 --- a/doc/doxygen/parameters/TOPPDocumenter.cpp +++ b/doc/doxygen/parameters/TOPPDocumenter.cpp @@ -100,7 +100,7 @@ void convertINI2HTML(const Param& p, ostream& os) s_attr += " item_advanced"; // optionally add advanced class if (it->tags.find("required") != it->tags.end()) s_req += " item_required"; // optionally add required class - DataValue::DataType value_type = it->value.valueType(); + ParamValue::ValueType value_type = it->value.valueType(); //write opening tag os << indentation << "
::const_iterator tag_it = it->tags.begin(); tag_it != it->tags.end(); ++tag_it) + for (auto tag_it = it->tags.begin(); tag_it != it->tags.end(); ++tag_it) { if (*tag_it == "advanced") continue; // do not list "advanced" or "required" (this is done by color coding) @@ -139,8 +139,8 @@ void convertINI2HTML(const Param& p, ostream& os) String restrictions = ""; switch (value_type) { - case DataValue::INT_VALUE: - case DataValue::INT_LIST: + case ParamValue::INT_VALUE: + case ParamValue::INT_LIST: { bool min_set = (it->min_int != -numeric_limits::max()); bool max_set = (it->max_int != numeric_limits::max()); @@ -159,8 +159,8 @@ void convertINI2HTML(const Param& p, ostream& os) } break; - case DataValue::DOUBLE_VALUE: - case DataValue::DOUBLE_LIST: + case ParamValue::DOUBLE_VALUE: + case ParamValue::DOUBLE_LIST: { bool min_set = (it->min_float != -numeric_limits::max()); bool max_set = (it->max_float != numeric_limits::max()); @@ -179,8 +179,8 @@ void convertINI2HTML(const Param& p, ostream& os) } break; - case DataValue::STRING_VALUE: - case DataValue::STRING_LIST: + case ParamValue::STRING_VALUE: + case ParamValue::STRING_LIST: if (it->valid_strings.size() != 0) { restrictions.concatenate(it->valid_strings.begin(), it->valid_strings.end(), ","); diff --git a/doc/doxygen/public/TOPP.doxygen b/doc/doxygen/public/TOPP.doxygen index 57a18d9405d..c19ad547214 100755 --- a/doc/doxygen/public/TOPP.doxygen +++ b/doc/doxygen/public/TOPP.doxygen @@ -118,7 +118,6 @@ - @subpage TOPP_CompNovo - Performs a peptide/protein identification with the CompNovo engine. - @subpage TOPP_CompNovoCID - Performs a peptide/protein identification with the CompNovo engine in CID mode. - @subpage TOPP_CruxAdapter - Identifies peptides in MS/MS spectra via Crux and tide-search (external). - - @subpage TOPP_InspectAdapter - Identifies MS/MS spectra using Inspect (external). - @subpage TOPP_MascotAdapter - Identifies MS/MS spectra using Mascot (external). - @subpage TOPP_MascotAdapterOnline - Identifies MS/MS spectra using Mascot (external). - @subpage TOPP_MSGFPlusAdapter - Identifies MS/MS spectra using MSGFPlus (external). diff --git a/doc/doxygen/public/UTILS.doxygen b/doc/doxygen/public/UTILS.doxygen index 5b16874cded..9695a5943ad 100644 --- a/doc/doxygen/public/UTILS.doxygen +++ b/doc/doxygen/public/UTILS.doxygen @@ -53,7 +53,6 @@ - @subpage UTILS_PeakPickerIterative - A tool for peak detection in profile data. File Handling - - @subpage UTILS_CVInspector - A tool for visualization and validation of PSI mapping and CV files. - @subpage UTILS_FuzzyDiff - Compares two files, tolerating numeric differences. - @subpage UTILS_IDSplitter - Splits protein/peptide identifications off of annotated data files. - @subpage UTILS_MzMLSplitter - Splits an mzML file into multiple parts. diff --git a/share/OpenMS/examples/IonMobility_Evosep_HeLa.mzML.gz b/share/OpenMS/examples/IonMobility_Evosep_HeLa.mzML.gz new file mode 100644 index 00000000000..cfdd4c58fd9 Binary files /dev/null and b/share/OpenMS/examples/IonMobility_Evosep_HeLa.mzML.gz differ diff --git a/src/openms/include/OpenMS/ANALYSIS/ID/PeptideIndexing.h b/src/openms/include/OpenMS/ANALYSIS/ID/PeptideIndexing.h index 3602e29c19e..36374da5a98 100644 --- a/src/openms/include/OpenMS/ANALYSIS/ID/PeptideIndexing.h +++ b/src/openms/include/OpenMS/ANALYSIS/ID/PeptideIndexing.h @@ -749,7 +749,7 @@ namespace OpenMS if ((stats_count_m_d + stats_count_m_td) == 0) { - String msg("No peptides were matched to the decoy portion of the database! Did you provide the correct concatenated database? Are your 'decoy_string' (=" + String(decoy_string_) + ") and 'decoy_string_position' (=" + String(param_.getValue("decoy_string_position")) + ") settings correct?"); + String msg("No peptides were matched to the decoy portion of the database! Did you provide the correct concatenated database? Are your 'decoy_string' (=" + decoy_string_ + ") and 'decoy_string_position' (=" + std::string(param_.getValue("decoy_string_position")) + ") settings correct?"); if (missing_decoy_action_ == MissingDecoy::IS_ERROR) { OPENMS_LOG_ERROR << "Error: " << msg << "\nSet 'missing_decoy_action' to 'warn' if you are sure this is ok!\nAborting ..." << std::endl; diff --git a/src/openms/include/OpenMS/ANALYSIS/ID/SiriusAdapterAlgorithm.h b/src/openms/include/OpenMS/ANALYSIS/ID/SiriusAdapterAlgorithm.h index 94ff7f5954d..8aad76680b9 100644 --- a/src/openms/include/OpenMS/ANALYSIS/ID/SiriusAdapterAlgorithm.h +++ b/src/openms/include/OpenMS/ANALYSIS/ID/SiriusAdapterAlgorithm.h @@ -193,7 +193,7 @@ namespace OpenMS explicit ParameterModifier(const String ¶m_name, SiriusAdapterAlgorithm *enclose) : openms_param_name(param_name), enclose(enclose) {} - void withValidStrings(initializer_list choices) + void withValidStrings(initializer_list choices) { enclose->defaults_.setValidStrings(openms_param_name, choices); } @@ -219,7 +219,7 @@ namespace OpenMS protected: ParameterModifier parameter( const String ¶meter_name, - const DataValue &default_value, + const ParamValue &default_value, const String ¶meter_description); void flag( const String ¶meter_name, diff --git a/src/openms/include/OpenMS/ANALYSIS/MAPMATCHING/TransformationDescription.h b/src/openms/include/OpenMS/ANALYSIS/MAPMATCHING/TransformationDescription.h index 244346786ad..4559a0b22ef 100644 --- a/src/openms/include/OpenMS/ANALYSIS/MAPMATCHING/TransformationDescription.h +++ b/src/openms/include/OpenMS/ANALYSIS/MAPMATCHING/TransformationDescription.h @@ -35,6 +35,7 @@ #pragma once #include +#include #include #include #include diff --git a/src/openms/include/OpenMS/ANALYSIS/MAPMATCHING/TransformationModel.h b/src/openms/include/OpenMS/ANALYSIS/MAPMATCHING/TransformationModel.h index 066f0b76742..328d58632d2 100644 --- a/src/openms/include/OpenMS/ANALYSIS/MAPMATCHING/TransformationModel.h +++ b/src/openms/include/OpenMS/ANALYSIS/MAPMATCHING/TransformationModel.h @@ -35,6 +35,7 @@ #pragma once #include +#include #include #include diff --git a/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/IsobaricQuantitationMethod.h b/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/IsobaricQuantitationMethod.h index 3fe47779114..5923755252a 100644 --- a/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/IsobaricQuantitationMethod.h +++ b/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/IsobaricQuantitationMethod.h @@ -36,6 +36,7 @@ #include #include +#include #include @@ -146,7 +147,7 @@ namespace OpenMS @param stringlist The StringList to convert. @return An isotope correction matrix as Matrix. */ - Matrix stringListToIsotopCorrectionMatrix_(const StringList& stringlist) const; + Matrix stringListToIsotopCorrectionMatrix_(const std::vector& stringlist) const; }; } // namespace diff --git a/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTElevenPlexQuantitationMethod.h b/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTElevenPlexQuantitationMethod.h index 2fd747b6bde..ff2ebaaba4b 100644 --- a/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTElevenPlexQuantitationMethod.h +++ b/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTElevenPlexQuantitationMethod.h @@ -87,7 +87,7 @@ namespace OpenMS Size reference_channel_; /// List of available channel names as they are presented to the user - static const std::vector channel_names_; + static const std::vector channel_names_; protected: /// implemented for DefaultParamHandler diff --git a/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTSixteenPlexQuantitationMethod.h b/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTSixteenPlexQuantitationMethod.h index b07f11e679d..1fee056273d 100644 --- a/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTSixteenPlexQuantitationMethod.h +++ b/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTSixteenPlexQuantitationMethod.h @@ -87,7 +87,7 @@ namespace OpenMS Size reference_channel_; /// List of available channel names as they are presented to the user - static const std::vector channel_names_; + static const std::vector channel_names_; protected: /// implemented for DefaultParamHandler diff --git a/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTTenPlexQuantitationMethod.h b/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTTenPlexQuantitationMethod.h index a4fd963f857..fcee6f50df2 100644 --- a/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTTenPlexQuantitationMethod.h +++ b/src/openms/include/OpenMS/ANALYSIS/QUANTITATION/TMTTenPlexQuantitationMethod.h @@ -87,7 +87,7 @@ namespace OpenMS Size reference_channel_; /// List of available channel names as they are presented to the user - static const std::vector channel_names_; + static const std::vector channel_names_; protected: /// implemented for DefaultParamHandler diff --git a/src/openms/include/OpenMS/APPLICATIONS/MapAlignerBase.h b/src/openms/include/OpenMS/APPLICATIONS/MapAlignerBase.h index 4cffc7b4abd..c14c3ef664c 100644 --- a/src/openms/include/OpenMS/APPLICATIONS/MapAlignerBase.h +++ b/src/openms/include/OpenMS/APPLICATIONS/MapAlignerBase.h @@ -84,7 +84,7 @@ class TOPPMapAlignerBase : Param params; params.setValue("type", default_model, "Type of model"); // TODO: avoid referring to each TransformationModel subclass explicitly - StringList model_types = ListUtils::create("linear,b_spline,lowess,interpolated"); + std::vector model_types = {"linear","b_spline","lowess","interpolated"}; if (!ListUtils::contains(model_types, default_model)) { model_types.insert(model_types.begin(), default_model); diff --git a/src/openms/include/OpenMS/APPLICATIONS/OpenSwathBase.h b/src/openms/include/OpenMS/APPLICATIONS/OpenSwathBase.h index c18d632abc6..40b299119de 100644 --- a/src/openms/include/OpenMS/APPLICATIONS/OpenSwathBase.h +++ b/src/openms/include/OpenMS/APPLICATIONS/OpenSwathBase.h @@ -403,7 +403,7 @@ class TOPPOpenSwathBase : model_params.setValue("symmetric_regression", "false"); model_params.setValue("span", irt_detection_param.getValue("lowess:span")); model_params.setValue("num_nodes", irt_detection_param.getValue("b_spline:num_nodes")); - String model_type = irt_detection_param.getValue("alignmentMethod"); + String model_type = irt_detection_param.getValue("alignmentMethod").toString(); trafo_rtnorm.fitModel(model_type, model_params); } else if (!irt_tr_file.empty()) diff --git a/src/openms/include/OpenMS/APPLICATIONS/ParameterInformation.h b/src/openms/include/OpenMS/APPLICATIONS/ParameterInformation.h index 46901f4ca2a..39f97e82734 100644 --- a/src/openms/include/OpenMS/APPLICATIONS/ParameterInformation.h +++ b/src/openms/include/OpenMS/APPLICATIONS/ParameterInformation.h @@ -36,7 +36,7 @@ #include #include -#include +#include namespace OpenMS { @@ -70,7 +70,7 @@ namespace OpenMS /// type of the parameter ParameterTypes type; /// default value of the parameter stored as string - DataValue default_value; + ParamValue default_value; /// description of the parameter String description; /// argument in the description @@ -84,7 +84,7 @@ namespace OpenMS ///@name Restrictions for different parameter types //@{ - std::vector valid_strings; + StringList valid_strings; Int min_int; Int max_int; double min_float; @@ -92,7 +92,7 @@ namespace OpenMS //@} /// Constructor that takes all members in declaration order - ParameterInformation(const String& n, ParameterTypes t, const String& arg, const DataValue& def, const String& desc, bool req, bool adv, const StringList& tag_values = StringList()); + ParameterInformation(const String& n, ParameterTypes t, const String& arg, const ParamValue& def, const String& desc, bool req, bool adv, const StringList& tag_values = StringList()); ParameterInformation(); diff --git a/src/openms/include/OpenMS/APPLICATIONS/TOPPBase.h b/src/openms/include/OpenMS/APPLICATIONS/TOPPBase.h index 83493a19c00..e8b8721c5e6 100644 --- a/src/openms/include/OpenMS/APPLICATIONS/TOPPBase.h +++ b/src/openms/include/OpenMS/APPLICATIONS/TOPPBase.h @@ -354,7 +354,7 @@ namespace OpenMS bool getParamAsBool_(const String& key) const; /** - @brief Return the value @p key of parameters as DataValue. DataValue::EMPTY indicates that a parameter was not found. + @brief Return the value @p key of parameters as DataValue. ParamValue::EMPTY indicates that a parameter was not found. Parameters are searched in this order: -# command line @@ -364,7 +364,7 @@ namespace OpenMS where "some_key" == key in the examples. */ - const DataValue& getParam_(const String& key) const; + const ParamValue& getParam_(const String& key) const; /** @brief Get the part of a parameter name that makes up the subsection diff --git a/src/openms/include/OpenMS/CHEMISTRY/DigestionEnzymeDB.h b/src/openms/include/OpenMS/CHEMISTRY/DigestionEnzymeDB.h index 24895406be8..bf939dd98a1 100644 --- a/src/openms/include/OpenMS/CHEMISTRY/DigestionEnzymeDB.h +++ b/src/openms/include/OpenMS/CHEMISTRY/DigestionEnzymeDB.h @@ -188,7 +188,7 @@ namespace OpenMS if (param.empty()) return; std::vector split; - param.begin().getName().split(':', split); + String(param.begin().getName()).split(':', split); if (split[0] != "Enzymes") { throw Exception::ParseError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, split[0], "name 'Enzymes' expected"); @@ -201,7 +201,7 @@ namespace OpenMS // this iterates over all the "ITEM" elements in the XML file: for (Param::ParamIterator it = param.begin(); it != param.end(); ++it) { - it.getName().split(':', split); + String(it.getName()).split(':', split); if (split[0] != "Enzymes") break; // unexpected content in the XML file if (split[1] != previous_enzyme) { @@ -210,7 +210,7 @@ namespace OpenMS previous_enzyme = split[1]; values.clear(); } - values[it.getName()] = it->value; + values[it.getName()] = String(it->value.toString()); } // add last enzyme addEnzyme_(parseEnzyme_(values)); diff --git a/src/openms/include/OpenMS/CONCEPT/ClassTest.h b/src/openms/include/OpenMS/CONCEPT/ClassTest.h index e14d4afaf88..f485e195846 100644 --- a/src/openms/include/OpenMS/CONCEPT/ClassTest.h +++ b/src/openms/include/OpenMS/CONCEPT/ClassTest.h @@ -106,6 +106,13 @@ namespace OpenMS return true; } + /// This overload returns true; @c ParamValue will be converted to double by #TEST_REAL_SIMILAR. + inline bool OPENMS_DLLAPI + isRealType(const ParamValue&) + { + return true; + } + /// This overload returns true; @c DataValue will be converted to double by #TEST_REAL_SIMILAR. inline bool OPENMS_DLLAPI isRealType(const DataValue&) diff --git a/src/openms/include/OpenMS/CONCEPT/Constants.h b/src/openms/include/OpenMS/CONCEPT/Constants.h index 80c8b5ce11e..f1db15612aa 100644 --- a/src/openms/include/OpenMS/CONCEPT/Constants.h +++ b/src/openms/include/OpenMS/CONCEPT/Constants.h @@ -72,15 +72,15 @@ namespace OpenMS //@{ /// PI - extern OPENMS_DLLAPI const double PI; + inline const double PI = 3.14159265358979323846; /// Euler's number - base of the natural logarithm - extern OPENMS_DLLAPI const double E; + inline const double E = 2.718281828459045235; /** Internal threshold for equality comparisons. Default value is 1e-6. */ - extern OPENMS_DLLAPI double EPSILON; + inline double EPSILON = 1e-6; //@} /** @name Chemical/physical constants. @@ -90,101 +90,101 @@ namespace OpenMS /** Elementary charge. In units of C (\f$1.60217738 \cdot 10^{-19} C\f$). */ - extern OPENMS_DLLAPI const double ELEMENTARY_CHARGE; // C + inline const double ELEMENTARY_CHARGE = 1.60217738E-19; // C /// Elementary charge (alias) - extern OPENMS_DLLAPI const double e0; + inline const double e0 = ELEMENTARY_CHARGE; /** Electron mass. In units of kg (\f$9.1093897 \cdot 10^{-31}\f$ kg). */ - extern OPENMS_DLLAPI const double ELECTRON_MASS; // kg + inline const double ELECTRON_MASS = 9.1093897E-31; // kg /** Electron mass In units (\f$1,822.88850204(77)^{-1}\f$u). */ - extern OPENMS_DLLAPI const double ELECTRON_MASS_U; // u + inline const double ELECTRON_MASS_U = 1.0 / 1822.8885020477; // u /** Proton mass. In units of kg (\f$1.6726230 \cdot 10^{-27}\f$ kg). */ - extern OPENMS_DLLAPI const double PROTON_MASS; // kg + inline const double PROTON_MASS = 1.6726230E-27; // kg /** Proton mass. In units (\f$1.00727646677(10)\f$u) */ - extern OPENMS_DLLAPI const double PROTON_MASS_U; // u + inline const double PROTON_MASS_U = 1.0072764667710; // u /** C13C12 mass difference. In units (\f$1.0033548\f$u) */ - extern OPENMS_DLLAPI const double C13C12_MASSDIFF_U; // u + inline const double C13C12_MASSDIFF_U = 1.0033548378; // u /** Neutron mass. In units of kg (\f$1.6749286 \cdot 10^{-27}\f$ kg). */ - extern OPENMS_DLLAPI const double NEUTRON_MASS; // kg + inline const double NEUTRON_MASS = 1.6749286E-27; // kg /** Neutron mass. In units (\f$1.0086649156(6)\f$u) */ - extern OPENMS_DLLAPI const double NEUTRON_MASS_U; // u + inline const double NEUTRON_MASS_U = 1.00866491566; // u /** Avogadro constant. In units of \f$mol^{-1}\f$ (\f$6.0221367 \cdot 10^{23} mol^{-1}\f$). */ - extern OPENMS_DLLAPI const double AVOGADRO; + inline const double AVOGADRO = 6.0221367E+23; // 1 / mol /** Avogadro constant (alias) */ - extern OPENMS_DLLAPI const double NA; + inline const double NA = AVOGADRO; /** Avogadro constant (alias) */ - extern OPENMS_DLLAPI const double MOL; + inline const double MOL = AVOGADRO; /** Boltzmann constant. In units of J/K (\f$1.380657 \cdot 10^{-23}\f$ J/K). */ - extern OPENMS_DLLAPI const double BOLTZMANN; + inline const double BOLTZMANN = 1.380657E-23; // J / K /** Boltzmann constant (alias) */ - extern OPENMS_DLLAPI const double k; + inline const double k = BOLTZMANN; /** Planck constant. In units of Js (\f$6.6260754 \cdot 10^{-34}\f$ Js). */ - extern OPENMS_DLLAPI const double PLANCK; + inline const double PLANCK = 6.6260754E-34; // J * sec /** Planck constant (alias) */ - extern OPENMS_DLLAPI const double h; + inline const double h = PLANCK; /** Gas constant (= NA * k) */ - extern OPENMS_DLLAPI const double GAS_CONSTANT; + inline const double GAS_CONSTANT = NA * k; /** Gas constant (alias) */ - extern OPENMS_DLLAPI const double R; + inline const double R = GAS_CONSTANT; /** Faraday constant (= NA * e0) */ - extern OPENMS_DLLAPI const double FARADAY; + inline const double FARADAY = NA * e0; /** Faraday constant (alias) */ - extern OPENMS_DLLAPI const double F; + inline const double F = FARADAY; /** Bohr radius. In units m (\f$5.29177249 \cdot 10^{-11}\f$ m). */ - extern OPENMS_DLLAPI const double BOHR_RADIUS; + inline const double BOHR_RADIUS = 5.29177249E-11; // m /** Bohr radius (alias) */ - extern OPENMS_DLLAPI const double a0; + inline const double a0 = BOHR_RADIUS; // the following values from: // P.W.Atkins: Physical Chemistry, 5th ed., Oxford University Press, 1995 @@ -192,31 +192,31 @@ namespace OpenMS /** Vacuum permittivity. In units of \f$C^2J^{-1}m^{-1}\f$ (\f$8.85419 \cdot 10^{-12} C^2J^{-1}m^{-1}\f$). */ - extern OPENMS_DLLAPI const double VACUUM_PERMITTIVITY; + inline const double VACUUM_PERMITTIVITY = 8.85419E-12; // C^2 / (J * m) /** Vacuum permeability. In units of \f$Js^2C^{-2}m^{-1}\f$ (\f$4\pi \cdot 10^{-7} Js^2C^{-2}m^{-1}\f$). */ - extern OPENMS_DLLAPI const double VACUUM_PERMEABILITY; + inline const double VACUUM_PERMEABILITY = (4 * PI * 1E-7); // J s^2 / (C^2 * m) /** Speed of light. In units of m/s (\f$2.99792458 \cdot 10^8 ms^{-1}\f$). */ - extern OPENMS_DLLAPI const double SPEED_OF_LIGHT; + inline const double SPEED_OF_LIGHT = 2.99792458E+8; // m / s /** Speed of Light (alias) */ - extern OPENMS_DLLAPI const double c; + inline const double c = SPEED_OF_LIGHT; /** Gravitational constant. In units of \f$Nm^2kg^{-2}\f$ (\f$6.67259 \cdot 10^{-11} Nm^2kg^{-2}\f$). */ - extern OPENMS_DLLAPI const double GRAVITATIONAL_CONSTANT; + inline const double GRAVITATIONAL_CONSTANT = 6.67259E-11; // N m^2 / kg^2 /** Fine structure constant. Without unit (\f$7.29735 \cdot 10^{-3}\f$). */ - extern OPENMS_DLLAPI const double FINE_STRUCTURE_CONSTANT; + inline const double FINE_STRUCTURE_CONSTANT = 7.29735E-3; // 1 //@} /** @name Conversion factors @@ -226,214 +226,215 @@ namespace OpenMS /** Degree per rad. 57.2957795130823209 */ - extern OPENMS_DLLAPI const double DEG_PER_RAD; + inline const double DEG_PER_RAD = 57.2957795130823209; /** Rad per degree. 0.0174532925199432957 */ - extern OPENMS_DLLAPI const double RAD_PER_DEG; + inline const double RAD_PER_DEG = 0.0174532925199432957; /** mm per inch. 25.4 */ - extern OPENMS_DLLAPI const double MM_PER_INCH; + inline const double MM_PER_INCH = 25.4; /** m per foot. 3.048 */ - extern OPENMS_DLLAPI const double M_PER_FOOT; + inline const double M_PER_FOOT = 3.048; /** Joules per calorie. 4.184 */ - extern OPENMS_DLLAPI const double JOULE_PER_CAL; + inline const double JOULE_PER_CAL = 4.184; /** Calories per Joule. 1/JOULE_PER_CAL */ - extern OPENMS_DLLAPI const double CAL_PER_JOULE; + inline const double CAL_PER_JOULE = (1 / 4.184); namespace UserParam { /** User parameter name for identifier of concatenated peptides String */ - extern OPENMS_DLLAPI const std::string CONCAT_PEPTIDE; + inline const std::string CONCAT_PEPTIDE = "concatenated_peptides"; /** Metavalue to list unimod modifications used in site localization */ - extern OPENMS_DLLAPI const std::string LOCALIZED_MODIFICATIONS_USERPARAM; + inline const std::string LOCALIZED_MODIFICATIONS_USERPARAM = "localized_modifications"; /** User parameter name for the M/Z of other chromatograms which have been merged into this one String */ - extern OPENMS_DLLAPI const std::string MERGED_CHROMATOGRAM_MZS; + inline const std::string MERGED_CHROMATOGRAM_MZS = "merged_chromatogram_mzs"; /** User parameter name for precursor mz error in ppm String */ - extern OPENMS_DLLAPI const std::string PRECURSOR_ERROR_PPM_USERPARAM; + inline const std::string PRECURSOR_ERROR_PPM_USERPARAM = "precursor_mz_error_ppm"; /** User parameter name for median of fragment mz error in ppm String */ - extern OPENMS_DLLAPI const std::string FRAGMENT_ERROR_MEDIAN_PPM_USERPARAM; + inline const std::string FRAGMENT_ERROR_MEDIAN_PPM_USERPARAM = "fragment_mz_error_median_ppm"; + /** User parameter name for fragment mz error in ppm String */ - extern OPENMS_DLLAPI const std::string FRAGMENT_ERROR_PPM_USERPARAM; + inline const std::string FRAGMENT_ERROR_PPM_USERPARAM = "fragment_mass_error_ppm"; /** User parameter name for fragment mz error in dalton String */ - extern OPENMS_DLLAPI const std::string FRAGMENT_ERROR_DA_USERPARAM; + inline const std::string FRAGMENT_ERROR_DA_USERPARAM = "fragment_mass_error_da"; /** User parameter name for fragment annotations String */ - extern OPENMS_DLLAPI const std::string FRAGMENT_ANNOTATION_USERPARAM; + inline const std::string FRAGMENT_ANNOTATION_USERPARAM = "fragment_annotation"; /** User parameter name for annotation of PSMExlpainedIonCurrent String */ - extern OPENMS_DLLAPI const std::string PSM_EXPLAINED_ION_CURRENT_USERPARAM; + inline const std::string PSM_EXPLAINED_ION_CURRENT_USERPARAM = "PSM_explained_ion_current"; /** User parameter name for the spectrum reference in PeptideIdentification (is is not yet treated as a class attribute) String */ - extern OPENMS_DLLAPI const std::string SPECTRUM_REFERENCE; + inline const std::string SPECTRUM_REFERENCE = "spectrum_reference"; /** User parameter name for target/decoy annotation of a PeptideHit, e.g. as annotated by PeptideIndexer. One of: target, decoy, target+decoy String */ - extern OPENMS_DLLAPI const std::string TARGET_DECOY; + inline const std::string TARGET_DECOY = "target_decoy"; /** User parameter name for a delta score: a score ratio between a rank x hit and the rank x+1 hit String */ - extern OPENMS_DLLAPI const std::string DELTA_SCORE; + inline const std::string DELTA_SCORE = "delta_score"; /** User parameter name to indicate a monoisotopic peak misassignment. Used for precursor correction. (usually an integer x with the correction being -x times C13C12_MASSDIFF_U) String */ - extern OPENMS_DLLAPI const std::string ISOTOPE_ERROR; + inline const std::string ISOTOPE_ERROR = "isotope_error"; // Cross-Linking Mass Spectrometry user parameters /** Name of OpenPepXL main score (PSI CV term) String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_SCORE; + inline const std::string OPENPEPXL_SCORE = "OpenPepXL:score"; /** User parameter name for the sequence of the second peptide in a cross-link String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_BETA_SEQUENCE; + inline const std::string OPENPEPXL_BETA_SEQUENCE = "sequence_beta"; /** User parameter name for the protein accessions of the second peptide in a cross-link String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_BETA_ACCESSIONS; + inline const std::string OPENPEPXL_BETA_ACCESSIONS = "accessions_beta"; /** User parameter name for the 1st position of cross-link (alpha peptide position in a real cross-link, 1st of two positions in a loop-link, modified position in a mono-link) String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_XL_POS1; + inline const std::string OPENPEPXL_XL_POS1 = "xl_pos1"; /** User parameter name for the 2nd position of cross-link (beta peptide position in a real cross-link, 2nd of two positions in a loop-link, "-" in a mono-link) String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_XL_POS2; + inline const std::string OPENPEPXL_XL_POS2 = "xl_pos2"; /** User parameter name for the 1st cross-link position on the protein String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_XL_POS1_PROT; + inline const std::string OPENPEPXL_XL_POS1_PROT = "xl_pos1_protein"; /** User parameter name for the 2nd cross-link position on the protein String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_XL_POS2_PROT; + inline const std::string OPENPEPXL_XL_POS2_PROT = "xl_pos2_protein"; /** User parameter name for the cross-link type, one of: cross-link, loop-link, mono-link String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_XL_TYPE; + inline const std::string OPENPEPXL_XL_TYPE = "xl_type"; /** User parameter name for the cross-link rank (ranks of PeptideHits across different PeptideIdentifications) String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_XL_RANK; + inline const std::string OPENPEPXL_XL_RANK = "xl_rank"; /** User parameter name for the name of a cross-link String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_XL_MOD; + inline const std::string OPENPEPXL_XL_MOD = "xl_mod"; /** User parameter name for the mass of a cross-link String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_XL_MASS; + inline const std::string OPENPEPXL_XL_MASS = "xl_mass"; /** User parameter name for the terminal specificity of a cross-link on the alpha peptide (to distinguish a link to the first or last residue side chain from a terminal link) String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_XL_TERM_SPEC_ALPHA; + inline const std::string OPENPEPXL_XL_TERM_SPEC_ALPHA = "xl_term_spec_alpha"; /** User parameter name for the terminal specificity of a cross-link on the beta peptide (to distinguish a link to the first or last residue side chain from a terminal link) String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_XL_TERM_SPEC_BETA; + inline const std::string OPENPEPXL_XL_TERM_SPEC_BETA = "xl_term_spec_beta"; /** User parameter name for the RT of the heavy spectrum precursor in a labeled cross-linking experiment String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_HEAVY_SPEC_RT; + inline const std::string OPENPEPXL_HEAVY_SPEC_RT = "spec_heavy_RT"; /** User parameter name for the m/z of the heavy spectrum precursor in a labeled cross-linking experiment String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_HEAVY_SPEC_MZ; + inline const std::string OPENPEPXL_HEAVY_SPEC_MZ = "spec_heavy_MZ"; /** User parameter name for the spectrum reference of the heavy spectrum in a labeled cross-linking experiment String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_HEAVY_SPEC_REF; + inline const std::string OPENPEPXL_HEAVY_SPEC_REF = "spectrum_reference_heavy"; /** User parameter name for target/decoy annotation of alpha peptides String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_TARGET_DECOY_ALPHA; + inline const std::string OPENPEPXL_TARGET_DECOY_ALPHA = "xl_target_decoy_alpha"; /** User parameter name for target/decoy annotation of beta peptides String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_TARGET_DECOY_BETA; + inline const std::string OPENPEPXL_TARGET_DECOY_BETA = "xl_target_decoy_beta"; /** User parameter name for PeptideEvidence info for the beta/acceptor peptide: pre String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_BETA_PEPEV_PRE; + inline const std::string OPENPEPXL_BETA_PEPEV_PRE = "BetaPepEv:pre"; /** User parameter name for PeptideEvidence info for the beta/acceptor peptide: post String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_BETA_PEPEV_POST; + inline const std::string OPENPEPXL_BETA_PEPEV_POST = "BetaPepEv:post"; /** User parameter name for PeptideEvidence info for the beta/acceptor peptide: start String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_BETA_PEPEV_START; + inline const std::string OPENPEPXL_BETA_PEPEV_START = "BetaPepEv:start"; /** User parameter name for PeptideEvidence info for the beta/acceptor peptide: end String */ - extern OPENMS_DLLAPI const std::string OPENPEPXL_BETA_PEPEV_END; + inline const std::string OPENPEPXL_BETA_PEPEV_END = "BetaPepEv:end"; /** User parameter name for XL-MS FDR values String */ - extern OPENMS_DLLAPI const std::string XFDR_FDR; + inline const std::string XFDR_FDR = "XFDR:FDR"; } //@} diff --git a/src/openms/include/OpenMS/DATASTRUCTURES/DataValue.h b/src/openms/include/OpenMS/DATASTRUCTURES/DataValue.h index 9b81c829c56..212781159f3 100644 --- a/src/openms/include/OpenMS/DATASTRUCTURES/DataValue.h +++ b/src/openms/include/OpenMS/DATASTRUCTURES/DataValue.h @@ -44,6 +44,8 @@ class QString; namespace OpenMS { + class ParamValue; + /** @brief Class to hold strings, numeric values, lists of strings and lists of numeric values. @@ -125,6 +127,8 @@ namespace OpenMS DataValue(long long); /// specific constructor for unsigned long long int values (note: the implementation uses SignedSize) DataValue(unsigned long long); + /// specific constructor for ParamValue + DataValue(const ParamValue&); /// Destructor ~DataValue(); //@} diff --git a/src/openms/include/OpenMS/DATASTRUCTURES/FASTAContainer.h b/src/openms/include/OpenMS/DATASTRUCTURES/FASTAContainer.h index 795a5a0cecc..24a980595d9 100644 --- a/src/openms/include/OpenMS/DATASTRUCTURES/FASTAContainer.h +++ b/src/openms/include/OpenMS/DATASTRUCTURES/FASTAContainer.h @@ -343,9 +343,9 @@ class DecoyHelper public: struct Result { - bool success; //< did >=40% of proteins have the *same* prefix or suffix - String name; //< on success, what was the decoy string? - bool is_prefix; //< on success, was it a prefix or suffix + bool success; ///< did more than 40% of proteins have the *same* prefix or suffix + String name; ///< on success, what was the decoy string? + bool is_prefix; ///< on success, was it a prefix or suffix }; /** diff --git a/src/openms/include/OpenMS/DATASTRUCTURES/ListUtils.h b/src/openms/include/OpenMS/DATASTRUCTURES/ListUtils.h index ad438fdf3f1..ce21b930308 100644 --- a/src/openms/include/OpenMS/DATASTRUCTURES/ListUtils.h +++ b/src/openms/include/OpenMS/DATASTRUCTURES/ListUtils.h @@ -271,6 +271,11 @@ namespace OpenMS { return s.toFloat(); } + template<> + inline std::string convert(const String& s) + { + return static_cast(s); + } } template diff --git a/src/openms/include/OpenMS/DATASTRUCTURES/Param.h b/src/openms/include/OpenMS/DATASTRUCTURES/Param.h index 1d90d0e84d0..54682d643a9 100644 --- a/src/openms/include/OpenMS/DATASTRUCTURES/Param.h +++ b/src/openms/include/OpenMS/DATASTRUCTURES/Param.h @@ -34,20 +34,16 @@ #pragma once -#include -#include -#include +#include #include -#include #include +#include +#include namespace OpenMS { - template - class Map; - namespace Logger { class LogStream; @@ -80,7 +76,7 @@ namespace OpenMS /// Default constructor ParamEntry(); /// Constructor with name, description, value and advanced flag - ParamEntry(const String& n, const DataValue& v, const String& d, const StringList& t = StringList()); + ParamEntry(const std::string& n, const ParamValue& v, const std::string& d, const std::vector& t = std::vector()); /// Copy constructor ParamEntry(const ParamEntry&) = default; /// Move constructor @@ -94,25 +90,25 @@ namespace OpenMS ParamEntry& operator=(ParamEntry&&) & = default; /// Check if 'value' fulfills restrictions - bool isValid(String& message) const; + bool isValid(std::string& message) const; /// Equality operator (only name and value are compared) bool operator==(const ParamEntry& rhs) const; /// Name of the entry - String name; + std::string name; /// Description of the entry - String description; + std::string description; /// Value associated with the entry - DataValue value; + ParamValue value; /// Tags list, used e.g. for advanced parameter tag - std::set tags; + std::set tags; ///@name Restrictions to accepted values (used in checkDefaults) //@{ double min_float; ///< Default: - std::numeric_limits::max() double max_float; ///< Default: std::numeric_limits::max() - Int min_int; ///< Default: - std::numeric_limits::max() - Int max_int; ///< Default: std::numeric_limits::max() - std::vector valid_strings; ///< Default: empty + int min_int; ///< Default: - std::numeric_limits::max() + int max_int; ///< Default: std::numeric_limits::max() + std::vector valid_strings; ///< Default: empty //@} }; @@ -131,7 +127,7 @@ namespace OpenMS /// Default constructor ParamNode(); /// Constructor with name and description - ParamNode(const String& n, const String& d); + ParamNode(const std::string& n, const std::string& d); /// Copy constructor ParamNode(const ParamNode&) = default; /// Move constructor @@ -152,39 +148,39 @@ namespace OpenMS Returns the end iterator if no entry is found */ - EntryIterator findEntry(const String& name); + EntryIterator findEntry(const std::string& name); /** @brief Look up subnode of this node (local search) Returns the end iterator if no entry is found */ - NodeIterator findNode(const String& name); + NodeIterator findNode(const std::string& name); /** @brief Look up the parent node of the entry or node corresponding to @p name (tree search) Returns 0 if no entry is found */ - ParamNode* findParentOf(const String& name); + ParamNode* findParentOf(const std::string& name); /** @brief Look up the entry corresponding to @p name (tree search) Returns 0 if no entry is found */ - ParamEntry* findEntryRecursive(const String& name); + ParamEntry* findEntryRecursive(const std::string& name); ///Inserts a @p node with the given @p prefix - void insert(const ParamNode& node, const String& prefix = ""); + void insert(const ParamNode& node, const std::string& prefix = ""); ///Inserts an @p entry with the given @p prefix - void insert(const ParamEntry& entry, const String& prefix = ""); + void insert(const ParamEntry& entry, const std::string& prefix = ""); ///Returns the number of entries in the whole subtree - Size size() const; + size_t size() const; ///Returns the name suffix of a @p key (the part behind the last ':' character) - String suffix(const String& key) const; + std::string suffix(const std::string& key) const; /// Name of the node - String name; + std::string name; /// Description of the node - String description; + std::string description; /// Entries (leafs) in the node std::vector entries; /// Subnodes @@ -201,7 +197,7 @@ namespace OpenMS struct OPENMS_DLLAPI TraceInfo { /// Constructor with name, description, and open flag - inline TraceInfo(const String& n, const String& d, bool o) : + inline TraceInfo(const std::string& n, const std::string& d, bool o) : name(n), description(d), opened(o) @@ -209,9 +205,9 @@ namespace OpenMS } /// name of the node - String name; + std::string name; /// description of the node - String description; + std::string description; /// If it was opened (true) or closed (false) bool opened; }; @@ -235,7 +231,7 @@ namespace OpenMS /// Equality operator bool operator!=(const ParamIterator& rhs) const; /// Returns the absolute path of the current element (including all sections) - String getName() const; + std::string getName() const; /// Returns the traceback of the opened and closed sections const std::vector& getTrace() const; @@ -243,7 +239,7 @@ namespace OpenMS /// Pointer to the root node const Param::ParamNode* root_; /// Index of the current ParamEntry (-1 means invalid) - Int current_; + int current_; /// Pointers to the ParamNodes we are in std::vector stack_; /// Node traversal data during last ++ operation. @@ -289,21 +285,28 @@ namespace OpenMS @param description Verbose description of the parameter @param tags list of tags associated to this parameter */ - void setValue(const String& key, const DataValue& value, const String& description = "", const StringList& tags = StringList()); + void setValue(const std::string& key, const ParamValue& value, const std::string& description = "", const std::vector& tags = std::vector()); /** @brief Returns a value of a parameter. @exception Exception::ElementNotFound is thrown if the parameter does not exists. */ - const DataValue& getValue(const String& key) const; + const ParamValue& getValue(const std::string& key) const; + + /** + @brief Returns the type of a parameter. + + @exception Exception::ElementNotFound is thrown if the parameter does not exists. + */ + ParamValue::ValueType getValueType(const std::string& key) const; /** @brief Returns the whole parameter entry. @exception Exception::ElementNotFound is thrown if the parameter does not exists. */ - const ParamEntry& getEntry(const String& key) const; + const ParamEntry& getEntry(const std::string& key) const; /** @brief Tests if a parameter is set (expecting its fully qualified name, e.g., TextExporter:1:proteins_only) @@ -311,7 +314,15 @@ namespace OpenMS @param key The fully qualified name of the parameter to check. @return True if the parameter exists, false otherwise. */ - bool exists(const String& key) const; + bool exists(const std::string& key) const; + + /** + @brief Checks whether a section is present. + + @param key The key of the section to be searched for. May or may not contain ":" suffix. + @return True if the section exists, false otherwise. + */ + bool hasSection(const std::string& key) const; /** @brief Find leaf node by name (if it exists). @@ -319,7 +330,7 @@ namespace OpenMS @param leaf The name of the parameter to find excluding the path parameter, e.g., given the parameter TextExporter:1:proteins_only the leaf would be named proteins_only. @return Returns end() if leaf does not exist. */ - ParamIterator findFirst(const String& leaf) const; + ParamIterator findFirst(const std::string& leaf) const; /** @brief Find next leaf node by name (if it exists), not considering the @p start_leaf @@ -328,7 +339,7 @@ namespace OpenMS @param start_leaf The already found leaf, that should not be considered during this search. @return Returns end() if leaf does not exist. */ - ParamIterator findNext(const String& leaf, const ParamIterator& start_leaf) const; + ParamIterator findNext(const std::string& leaf, const ParamIterator& start_leaf) const; //@} ///@name Tags handling @@ -342,7 +353,7 @@ namespace OpenMS @exception Exception::ElementNotFound is thrown if the parameter does not exists. @exception Exception::InvalidValue is thrown if the tag contain a comma character. */ - void addTag(const String& key, const String& tag); + void addTag(const std::string& key, const std::string& tag); /** @brief Adds the tags in the list @p tags to the entry @p key @@ -350,7 +361,7 @@ namespace OpenMS @exception Exception::ElementNotFound is thrown if the parameter does not exists. @exception Exception::InvalidValue is thrown if a tag contain a comma character. */ - void addTags(const String& key, const StringList& tags); + void addTags(const std::string& key, const std::vector& tags); /** @brief Returns if the parameter @p key has a tag @@ -360,21 +371,21 @@ namespace OpenMS @exception Exception::ElementNotFound is thrown if the parameter does not exists. */ - bool hasTag(const String& key, const String& tag) const; + bool hasTag(const std::string& key, const std::string& tag) const; /** @brief Returns the tags of entry @p key @exception Exception::ElementNotFound is thrown if the parameter does not exists. */ - StringList getTags(const String& key) const; + std::vector getTags(const std::string& key) const; /** @brief Removes all tags from the entry @p key @exception Exception::ElementNotFound is thrown if the parameter does not exists. */ - void clearTags(const String& key); + void clearTags(const std::string& key); //@} @@ -386,7 +397,7 @@ namespace OpenMS @exception Exception::ElementNotFound is thrown if the parameter does not exists. */ - const String& getDescription(const String& key) const; + const std::string& getDescription(const std::string& key) const; /** @brief Sets a description for an existing section @@ -396,28 +407,28 @@ namespace OpenMS @exception Exception::ElementNotFound is thrown if the section does not exists. */ - void setSectionDescription(const String& key, const String& description); + void setSectionDescription(const std::string& key, const std::string& description); /** @brief Returns the description corresponding to the section with name @p key. If the section does not exist an empty string is returned. */ - const String& getSectionDescription(const String& key) const; + const std::string& getSectionDescription(const std::string& key) const; /** @brief Adds a parameter section under the path @p key with the given @p description. If the section already exists, the description is only overwritten if not empty. */ - void addSection(const String& key, const String& description); + void addSection(const std::string& key, const std::string& description); //@} ///@name Manipulation of the whole parameter set //@{ ///Returns the number of entries (leafs). - Size size() const; + size_t size() const; ///Returns if there are no entries. bool empty() const; @@ -427,7 +438,7 @@ namespace OpenMS /// Insert all values of @p param and adds the prefix @p prefix. /// You should append ':' to prefix manually when you want it to be a section. - void insert(const String& prefix, const Param& param); + void insert(const std::string& prefix, const Param& param); /** @brief Remove the entry @p key or a section @p key (when suffix is ':') @@ -438,7 +449,7 @@ namespace OpenMS If an empty internal node remains, the tree is pruned until every node has either a successor node or a leaf, i.e. no naked nodes remain. */ - void remove(const String& key); + void remove(const std::string& key); /** @brief Remove all entries that start with @p prefix @@ -448,7 +459,7 @@ namespace OpenMS If an empty internal node remains, the tree is pruned until every node has either a successor node or a leaf, i.e. no naked nodes remain. */ - void removeAll(const String& prefix); + void removeAll(const std::string& prefix); /** @brief Returns a new Param object containing all entries that start with @p prefix. @@ -457,7 +468,7 @@ namespace OpenMS Otherwise not only nodes, but as well values with that prefix are copied. @param remove_prefix indicates if the prefix is removed before adding entries to the new Param */ - Param copy(const String& prefix, bool remove_prefix = false) const; + Param copy(const std::string& prefix, bool remove_prefix = false) const; /** @brief Returns a new Param object containing all entries in the given subset. @@ -528,7 +539,7 @@ namespace OpenMS @see checkDefaults */ - void setDefaults(const Param& defaults, const String& prefix = "", bool showMessage = false); + void setDefaults(const Param& defaults, const std::string& prefix = "", bool showMessage = false); /** @brief Checks the current parameter entries against given @p defaults @@ -549,7 +560,7 @@ namespace OpenMS @exception Exception::InvalidParameter is thrown if errors occur during the check */ - void checkDefaults(const String& name, const Param& defaults, const String& prefix = "") const; + void checkDefaults(const std::string& name, const Param& defaults, const std::string& prefix = "") const; //@} ///@name Restriction handling @@ -562,7 +573,7 @@ namespace OpenMS @exception Exception::InvalidParameter is thrown, if one of the strings contains a comma character @exception Exception::ElementNotFound exception is thrown, if the parameter is no string parameter */ - void setValidStrings(const String& key, const std::vector& strings); + void setValidStrings(const std::string& key, const std::vector& strings); /** @brief Sets the minimum value for the integer or integer list parameter @p key. @@ -571,7 +582,7 @@ namespace OpenMS @exception Exception::ElementNotFound is thrown if @p key is not found or if the parameter type is wrong */ - void setMinInt(const String& key, Int min); + void setMinInt(const std::string& key, int min); /** @brief Sets the maximum value for the integer or integer list parameter @p key. @@ -580,7 +591,7 @@ namespace OpenMS @exception Exception::ElementNotFound is thrown if @p key is not found or if the parameter type is wrong */ - void setMaxInt(const String& key, Int max); + void setMaxInt(const std::string& key, int max); /** @brief Sets the minimum value for the floating point or floating point list parameter @p key. @@ -589,7 +600,7 @@ namespace OpenMS @exception Exception::ElementNotFound is thrown if @p key is not found or if the parameter type is wrong */ - void setMinFloat(const String& key, double min); + void setMinFloat(const std::string& key, double min); /** @brief Sets the maximum value for the floating point or floating point list parameter @p key. @@ -598,7 +609,7 @@ namespace OpenMS @exception Exception::ElementNotFound is thrown if @p key is not found or if the parameter type is wrong */ - void setMaxFloat(const String& key, double max); + void setMaxFloat(const std::string& key, double max); //@} ///@name Command line parsing @@ -621,7 +632,7 @@ namespace OpenMS @param argv argv variable from command line @param prefix prefix for all options */ - void parseCommandLine(const int argc, const char** argv, const String& prefix = ""); + void parseCommandLine(const int argc, const char** argv, const std::string& prefix = ""); /** @brief Parses command line arguments to specified key locations. @@ -636,7 +647,7 @@ namespace OpenMS @param misc key where a StringList of all non-option arguments are stored @param unknown key where a StringList of all unknown options are stored */ - void parseCommandLine(const int argc, const char** argv, const Map& options_with_one_argument, const Map& options_without_argument, const Map& options_with_multiple_argument, const String& misc = "misc", const String& unknown = "unknown"); + void parseCommandLine(const int argc, const char** argv, const std::map& options_with_one_argument, const std::map& options_without_argument, const std::map& options_with_multiple_argument, const std::string& misc = "misc", const std::string& unknown = "unknown"); //@} @@ -647,7 +658,7 @@ namespace OpenMS @exception Exception::ElementNotFound is thrown for unset parameters */ - ParamEntry& getEntry_(const String& key) const; + ParamEntry& getEntry_(const std::string& key) const; /// Constructor from a node which is used as root node Param(const Param::ParamNode& node); diff --git a/src/openms/include/OpenMS/DATASTRUCTURES/ParamValue.h b/src/openms/include/OpenMS/DATASTRUCTURES/ParamValue.h new file mode 100644 index 00000000000..d1b7af0ef74 --- /dev/null +++ b/src/openms/include/OpenMS/DATASTRUCTURES/ParamValue.h @@ -0,0 +1,396 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Authors: Ruben Grünberg $ +// -------------------------------------------------------------------------- + +#pragma once + +#include + +#include +#include + +namespace OpenMS +{ + /** + @brief Class to hold strings, numeric values, vectors of strings and vectors of numeric values using the stl types. + + - To choose one of these types, just use the appropriate constructor. + - Automatic conversion is supported and throws Exceptions in case of invalid conversions. + - An empty object is created with the default constructor. + + @ingroup Datastructures + */ + class OPENMS_DLLAPI ParamValue + { + +public: + + /// Empty data value for comparisons + static const ParamValue EMPTY; + + /// Supported types for ParamValue + enum ValueType : unsigned char + { + STRING_VALUE, ///< string value + INT_VALUE, ///< integer value + DOUBLE_VALUE, ///< double value + STRING_LIST, ///< string vector + INT_LIST, ///< integer vector + DOUBLE_LIST, ///< double vector + EMPTY_VALUE ///< empty value + }; + + /// @name Constructors and destructors + //@{ + /// Default constructor + ParamValue(); + /// Copy constructor + ParamValue(const ParamValue&); + /// Move constructor + ParamValue(ParamValue&&) noexcept; + /// specific constructor for char* (converted to string) + ParamValue(const char*); + /// specific constructor for std::string values + ParamValue(const std::string&); + /// specific constructor for string vectors + ParamValue(const std::vector&); + /// specific constructor for integer vectors + ParamValue(const std::vector&); + /// specific constructor for double vectors + ParamValue(const std::vector&); + /// specific constructor for long double values (note: the implementation uses double) + ParamValue(long double); + /// specific constructor for double values (note: the implementation uses double) + ParamValue(double); + /// specific constructor for float values (note: the implementation uses double) + ParamValue(float); + /// specific constructor for short int values (note: the implementation uses ptrdiff_t) + ParamValue(short int); + /// specific constructor for unsigned short int values (note: the implementation uses ptrdiff_t) + ParamValue(unsigned short int); + /// specific constructor for int values (note: the implementation uses ptrdiff_t) + ParamValue(int); + /// specific constructor for unsigned int values (note: the implementation uses ptrdiff_t) + ParamValue(unsigned); + /// specific constructor for long int values (note: the implementation uses ptrdiff_t) + ParamValue(long int); + /// specific constructor for unsigned long int values (note: the implementation uses ptrdiff_t) + ParamValue(unsigned long); + /// specific constructor for long long int values (note: the implementation uses ptrdiff_t) + ParamValue(long long); + /// specific constructor for unsigned long long int values (note: the implementation uses ptrdiff_t) + ParamValue(unsigned long long); + /// Destructor + ~ParamValue(); + //@} + + ///@name Cast operators + ///These methods are used when the DataType is known. + ///If they are applied to a ParamValue with the wrong DataType, an exception (Exception::ConversionError) is thrown. In particular, none of these operators will work for an empty ParamValue (DataType EMPTY_VALUE) - except toChar(), which will return 0. + //@{ + + /** + @brief conversion operator to string + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator std::string() const; + + /** + @brief conversion operator to string vector + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator std::vector() const; + + /** + @brief conversion operator to integer vector + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator std::vector() const; + + /** + @brief conversion operator to double vector + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator std::vector() const; + + /** + @brief conversion operator to long double + + Note: The implementation uses typedef double (as opposed to float, double, long double.) + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator long double() const; + + /** + @brief conversion operator to double + + Note: The implementation uses typedef double (as opposed to float, double, long double.) + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator double() const; + + /** + @brief conversion operator to float + + Note: The implementation uses typedef double (as opposed to float, double, long double.) + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator float() const; + + /** + @brief conversion operator to short int + + Note: The implementation uses typedef ptrdiff_t. + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator short int() const; + + /** + @brief conversion operator to unsigned short int + + Note: The implementation uses typedef ptrdiff_t. + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator unsigned short int() const; + + /** + @brief conversion operator to int + + Note: The implementation uses typedef ptrdiff_t. + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + + operator int() const; + + /** + @brief conversion operator to unsigned int + + Note: The implementation uses typedef ptrdiff_t. + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator unsigned int() const; + + /** + @brief conversion operator to long int + + Note: The implementation uses typedef ptrdiff_t. + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator long int() const; + + /** + @brief conversion operator to unsigned long int + + Note: The implementation uses typedef ptrdiff_t. + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator unsigned long int() const; + + /** + @brief conversion operator to long long + + Note: The implementation uses typedef ptrdiff_t. + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator long long() const; + + /** + @brief conversion operator to unsigned long long + + Note: The implementation uses typedef ptrdiff_t. + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + operator unsigned long long() const; + + /** + @brief Conversion to bool + + Converts the strings 'true' and 'false' to a bool. + + @exception Exception::ConversionError is thrown for non-string parameters and string parameters with values other than 'true' and 'false'. + */ + bool toBool() const; + + /** + @brief Convert ParamValues to char* + + If the ParamValue contains a string, a pointer to it's char* is returned. + If the ParamValue is empty, nullptr is returned. + */ + const char* toChar() const; + + /** + * @brief Convert ParamValue to string + * + * @exception Exception::ConversionError is thrown for ParamValue::EMPTY and + */ + + std::string toString(bool full_precision = true) const; + + /** + @brief Explicitly convert ParamValue to string vector + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + std::vector toStringVector() const; + + /** + @brief Explicitly convert ParamValue to IntList + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + std::vector toIntVector() const; + + /** + @brief Explicitly convert ParamValue to DoubleList + + @exception Exception::ConversionError is thrown if a cast from the the wrong type is requested + */ + std::vector toDoubleVector() const; + //@} + + ///@name Assignment operators + ///These methods are used to assign supported types directly to a ParamValue object. + //@{ + /// Assignment operator + ParamValue& operator=(const ParamValue&); + /// Move assignment operator + ParamValue& operator=(ParamValue&&) noexcept; + /// specific assignment for char* (converted to string) + ParamValue& operator=(const char*); + /// specific assignment for std::string values + ParamValue& operator=(const std::string&); + /// specific assignment for string vectors + ParamValue& operator=(const std::vector&); + /// specific assignment for integer vectors + ParamValue& operator=(const std::vector&); + /// specific assignment for double vectors + ParamValue& operator=(const std::vector&); + /// specific assignment for long double values (note: the implementation uses double) + ParamValue& operator=(const long double); + /// specific assignment for double values (note: the implementation uses double) + ParamValue& operator=(const double); + /// specific assignment for float values (note: the implementation uses double) + ParamValue& operator=(const float); + /// specific assignment for short int values (note: the implementation uses ptrdiff_t) + ParamValue& operator=(const short int); + /// specific assignment for unsigned short int values (note: the implementation uses ptrdiff_t) + ParamValue& operator=(const unsigned short int); + /// specific assignment for int values (note: the implementation uses ptrdiff_t) + ParamValue& operator=(const int); + /// specific assignment for unsigned int values (note: the implementation uses ptrdiff_t) + ParamValue& operator=(const unsigned); + /// specific assignment for long int values (note: the implementation uses ptrdiff_t) + ParamValue& operator=(const long int); + /// specific assignment for unsigned long int values (note: the implementation uses ptrdiff_t) + ParamValue& operator=(const unsigned long); + /// specific assignment for long long int values (note: the implementation uses ptrdiff_t) + ParamValue& operator=(const long long); + /// specific assignment for unsigned long long int values (note: the implementation uses ptrdiff_t) + ParamValue& operator=(const unsigned long long); + //@} + + /// returns the type of value stored + inline ValueType valueType() const + { + return value_type_; + } + + /** + @brief Test if the value is empty + + @note A ParamValue containing an empty string ("") does not count as empty! + */ + inline bool isEmpty() const + { + return value_type_ == EMPTY_VALUE; + } + + /// output stream operator + friend OPENMS_DLLAPI std::ostream& operator<<(std::ostream&, const ParamValue&); + + /// Equality comparator + friend OPENMS_DLLAPI bool operator==(const ParamValue&, const ParamValue&); + + /// Smaller than comparator (for vectors we use the size) + friend OPENMS_DLLAPI bool operator<(const ParamValue&, const ParamValue&); + + /// Greater than comparator (for vectors we use the size) + friend OPENMS_DLLAPI bool operator>(const ParamValue&, const ParamValue&); + + /// Equality comparator + friend OPENMS_DLLAPI bool operator!=(const ParamValue&, const ParamValue&); + +protected: + + /// Type of the currently stored value + ValueType value_type_; + + /// Space to store the data + union + { + ptrdiff_t ssize_; + double dou_; + std::string* str_; + std::vector* str_list_; + std::vector* int_list_; + std::vector* dou_list_; + } data_; + +private: + + /// Clears the current state of the ParamValue and release every used memory. + void clear_() noexcept; + + /// Convert a double to std::string + /// with full precision 15 decimal places are given, otherwise 3 + /// numbers above 10000 or below 0.0001 are given in scientific notation (i.e. 1.0e04) + static std::string doubleToString(double value, bool full_precision = true); + + }; +} + diff --git a/src/openms/include/OpenMS/DATASTRUCTURES/StringUtils.h b/src/openms/include/OpenMS/DATASTRUCTURES/StringUtils.h index 3872ece15f3..fd2747a9008 100644 --- a/src/openms/include/OpenMS/DATASTRUCTURES/StringUtils.h +++ b/src/openms/include/OpenMS/DATASTRUCTURES/StringUtils.h @@ -502,8 +502,8 @@ namespace OpenMS { if (method == String::ESCAPE) { - this_s.substitute(String("\\"), String("\\\\")); - this_s.substitute(String(q), "\\" + String(q)); + this_s.substitute(String(R"(\)"), String(R"(\\)")); + this_s.substitute(String(q), R"(\)" + String(q)); } else if (method == String::DOUBLE) this_s.substitute(String(q), String(q) + String(q)); @@ -523,8 +523,8 @@ namespace OpenMS this_s.std::string::operator=(this_s.substr(1, this_s.size() - 2)); // remove quotation marks if (method == String::ESCAPE) { - this_s.substitute("\\" + String(q), String(q)); - this_s.substitute(String("\\\\"), String("\\")); + this_s.substitute(R"(\)" + String(q), String(q)); + this_s.substitute(String(R"(\\)"), String(R"(\)")); } else if (method == String::DOUBLE) this_s.substitute(String(q) + String(q), String(q)); diff --git a/src/openms/include/OpenMS/DATASTRUCTURES/ToolDescription.h b/src/openms/include/OpenMS/DATASTRUCTURES/ToolDescription.h index 58e06054837..58f7ae01a1c 100644 --- a/src/openms/include/OpenMS/DATASTRUCTURES/ToolDescription.h +++ b/src/openms/include/OpenMS/DATASTRUCTURES/ToolDescription.h @@ -36,6 +36,7 @@ #include #include +#include #include diff --git a/src/openms/include/OpenMS/DATASTRUCTURES/sources.cmake b/src/openms/include/OpenMS/DATASTRUCTURES/sources.cmake index f86e7d7dc79..fbfd29b6a11 100644 --- a/src/openms/include/OpenMS/DATASTRUCTURES/sources.cmake +++ b/src/openms/include/OpenMS/DATASTRUCTURES/sources.cmake @@ -37,6 +37,7 @@ MatchedIterator.h Matrix.h OSWData.h Param.h +ParamValue.h QTCluster.h SeqanIncludeWrapper.h String.h diff --git a/src/openms/include/OpenMS/FILTERING/BASELINE/MorphologicalFilter.h b/src/openms/include/OpenMS/FILTERING/BASELINE/MorphologicalFilter.h index 2376216a033..d7d5327e627 100644 --- a/src/openms/include/OpenMS/FILTERING/BASELINE/MorphologicalFilter.h +++ b/src/openms/include/OpenMS/FILTERING/BASELINE/MorphologicalFilter.h @@ -172,10 +172,10 @@ namespace OpenMS //structuring element defaults_.setValue("struc_elem_length", 3.0, "Length of the structuring element. This should be wider than the expected peak width."); defaults_.setValue("struc_elem_unit", "Thomson", "The unit of the 'struct_elem_length'."); - defaults_.setValidStrings("struc_elem_unit", ListUtils::create("Thomson,DataPoints")); + defaults_.setValidStrings("struc_elem_unit", {"Thomson","DataPoints"}); //methods defaults_.setValue("method", "tophat", "Method to use, the default is 'tophat'. Do not change this unless you know what you are doing. The other methods may be useful for tuning the parameters, see the class documentation of MorpthologicalFilter."); - defaults_.setValidStrings("method", ListUtils::create("identity,erosion,dilation,opening,closing,gradient,tophat,bothat,erosion_simple,dilation_simple")); + defaults_.setValidStrings("method", {"identity","erosion","dilation","opening","closing","gradient","tophat","bothat","erosion_simple","dilation_simple"}); defaultsToParam_(); } @@ -210,7 +210,7 @@ namespace OpenMS } //apply the filtering - String method = param_.getValue("method"); + std::string method = param_.getValue("method"); if (method == "identity") { std::copy(input_begin, input_end, output_begin); @@ -291,7 +291,7 @@ namespace OpenMS if (spectrum.size() <= 1) { return; } //Determine structuring element size in datapoints (depending on the unit) - if ((String)(param_.getValue("struc_elem_unit")) == "Thomson") + if (param_.getValue("struc_elem_unit") == "Thomson") { const double struc_elem_length = (double)param_.getValue("struc_elem_length"); const double mz_diff = spectrum.back().getMZ() - spectrum.begin()->getMZ(); diff --git a/src/openms/include/OpenMS/FILTERING/ID/IDFilter.h b/src/openms/include/OpenMS/FILTERING/ID/IDFilter.h index 9ccdadff057..9bd891834ed 100644 --- a/src/openms/include/OpenMS/FILTERING/ID/IDFilter.h +++ b/src/openms/include/OpenMS/FILTERING/ID/IDFilter.h @@ -79,10 +79,10 @@ namespace OpenMS public: /// Constructor - IDFilter(); + IDFilter() = default; /// Destructor - virtual ~IDFilter(); + virtual ~IDFilter() = default; /// Typedefs typedef std::map ChargeToPepHitP; @@ -1061,6 +1061,10 @@ namespace OpenMS std::vector& peptides, const std::set& modifications); + static void removePeptidesWithMatchingRegEx( + std::vector& peptides, + const String& regex); + /// Keeps only peptide hits that have at least one of the given modifications static void keepPeptidesWithMatchingModifications( std::vector& peptides, diff --git a/src/openms/include/OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMeanIterative.h b/src/openms/include/OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMeanIterative.h index 2f2800b85b3..09c724521b6 100644 --- a/src/openms/include/OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMeanIterative.h +++ b/src/openms/include/OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMeanIterative.h @@ -96,19 +96,19 @@ namespace OpenMS " Only provide this parameter if you know what you are doing (and change 'auto_mode' to '-1')!" \ " All intensities EQUAL/ABOVE 'max_intensity' will not be added to the histogram." \ " If you choose 'max_intensity' too small, the noise estimate might be too small as well." \ - " If chosen too big, the bins become quite large (which you could counter by increasing 'bin_count', which increases runtime).", ListUtils::create("advanced")); + " If chosen too big, the bins become quite large (which you could counter by increasing 'bin_count', which increases runtime).", {"advanced"}); defaults_.setMinInt("max_intensity", -1); - defaults_.setValue("auto_max_stdev_factor", 3.0, "parameter for 'max_intensity' estimation (if 'auto_mode' == 0): mean + 'auto_max_stdev_factor' * stdev", ListUtils::create("advanced")); + defaults_.setValue("auto_max_stdev_factor", 3.0, "parameter for 'max_intensity' estimation (if 'auto_mode' == 0): mean + 'auto_max_stdev_factor' * stdev", {"advanced"}); defaults_.setMinFloat("auto_max_stdev_factor", 0.0); defaults_.setMaxFloat("auto_max_stdev_factor", 999.0); - defaults_.setValue("auto_max_percentile", 95, "parameter for 'max_intensity' estimation (if 'auto_mode' == 1): auto_max_percentile th percentile", ListUtils::create("advanced")); + defaults_.setValue("auto_max_percentile", 95, "parameter for 'max_intensity' estimation (if 'auto_mode' == 1): auto_max_percentile th percentile", {"advanced"}); defaults_.setMinInt("auto_max_percentile", 0); defaults_.setMaxInt("auto_max_percentile", 100); - defaults_.setValue("auto_mode", 0, "method to use to determine maximal intensity: -1 --> use 'max_intensity'; 0 --> 'auto_max_stdev_factor' method (default); 1 --> 'auto_max_percentile' method", ListUtils::create("advanced")); + defaults_.setValue("auto_mode", 0, "method to use to determine maximal intensity: -1 --> use 'max_intensity'; 0 --> 'auto_max_stdev_factor' method (default); 1 --> 'auto_max_percentile' method", {"advanced"}); defaults_.setMinInt("auto_mode", -1); defaults_.setMaxInt("auto_mode", 1); @@ -118,14 +118,14 @@ namespace OpenMS defaults_.setValue("bin_count", 30, "number of bins for intensity values"); defaults_.setMinInt("bin_count", 3); - defaults_.setValue("stdev_mp", 3.0, "multiplier for stdev", ListUtils::create("advanced")); + defaults_.setValue("stdev_mp", 3.0, "multiplier for stdev", {"advanced"}); defaults_.setMinFloat("stdev_mp", 0.01); defaults_.setMaxFloat("stdev_mp", 999.0); defaults_.setValue("min_required_elements", 10, "minimum number of elements required in a window (otherwise it is considered sparse)"); defaults_.setMinInt("min_required_elements", 1); - defaults_.setValue("noise_for_empty_window", std::pow(10.0, 20), "noise value used for sparse windows", ListUtils::create("advanced")); + defaults_.setValue("noise_for_empty_window", std::pow(10.0, 20), "noise value used for sparse windows", {"advanced"}); SignalToNoiseEstimator::defaultsToParam_(); } diff --git a/src/openms/include/OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMedian.h b/src/openms/include/OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMedian.h index a3b7342eb4c..298e9ef6a5f 100644 --- a/src/openms/include/OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMedian.h +++ b/src/openms/include/OpenMS/FILTERING/NOISEESTIMATION/SignalToNoiseEstimatorMedian.h @@ -107,18 +107,18 @@ namespace OpenMS " All intensities EQUAL/ABOVE 'max_intensity' will be added to the LAST histogram bin." \ " If you choose 'max_intensity' too small, the noise estimate might be too small as well. " \ " If chosen too big, the bins become quite large (which you could counter by increasing 'bin_count', which increases runtime)." \ - " In general, the Median-S/N estimator is more robust to a manual max_intensity than the MeanIterative-S/N.", ListUtils::create("advanced")); + " In general, the Median-S/N estimator is more robust to a manual max_intensity than the MeanIterative-S/N.", {"advanced"}); defaults_.setMinInt("max_intensity", -1); - defaults_.setValue("auto_max_stdev_factor", 3.0, "parameter for 'max_intensity' estimation (if 'auto_mode' == 0): mean + 'auto_max_stdev_factor' * stdev", ListUtils::create("advanced")); + defaults_.setValue("auto_max_stdev_factor", 3.0, "parameter for 'max_intensity' estimation (if 'auto_mode' == 0): mean + 'auto_max_stdev_factor' * stdev", {"advanced"}); defaults_.setMinFloat("auto_max_stdev_factor", 0.0); defaults_.setMaxFloat("auto_max_stdev_factor", 999.0); - defaults_.setValue("auto_max_percentile", 95, "parameter for 'max_intensity' estimation (if 'auto_mode' == 1): auto_max_percentile th percentile", ListUtils::create("advanced")); + defaults_.setValue("auto_max_percentile", 95, "parameter for 'max_intensity' estimation (if 'auto_mode' == 1): auto_max_percentile th percentile", {"advanced"}); defaults_.setMinInt("auto_max_percentile", 0); defaults_.setMaxInt("auto_max_percentile", 100); - defaults_.setValue("auto_mode", 0, "method to use to determine maximal intensity: -1 --> use 'max_intensity'; 0 --> 'auto_max_stdev_factor' method (default); 1 --> 'auto_max_percentile' method", ListUtils::create("advanced")); + defaults_.setValue("auto_mode", 0, "method to use to determine maximal intensity: -1 --> use 'max_intensity'; 0 --> 'auto_max_stdev_factor' method (default); 1 --> 'auto_max_percentile' method", {"advanced"}); defaults_.setMinInt("auto_mode", -1); defaults_.setMaxInt("auto_mode", 1); @@ -131,10 +131,10 @@ namespace OpenMS defaults_.setValue("min_required_elements", 10, "minimum number of elements required in a window (otherwise it is considered sparse)"); defaults_.setMinInt("min_required_elements", 1); - defaults_.setValue("noise_for_empty_window", std::pow(10.0, 20), "noise value used for sparse windows", ListUtils::create("advanced")); + defaults_.setValue("noise_for_empty_window", std::pow(10.0, 20), "noise value used for sparse windows", {"advanced"}); defaults_.setValue("write_log_messages", "true", "Write out log messages in case of sparse windows or median in rightmost histogram bin"); - defaults_.setValidStrings("write_log_messages", ListUtils::create("true,false")); + defaults_.setValidStrings("write_log_messages", {"true","false"}); SignalToNoiseEstimator::defaultsToParam_(); } diff --git a/src/openms/include/OpenMS/FILTERING/TRANSFORMERS/SpectraMerger.h b/src/openms/include/OpenMS/FILTERING/TRANSFORMERS/SpectraMerger.h index adc468069bb..8c3345f628b 100644 --- a/src/openms/include/OpenMS/FILTERING/TRANSFORMERS/SpectraMerger.h +++ b/src/openms/include/OpenMS/FILTERING/TRANSFORMERS/SpectraMerger.h @@ -314,10 +314,10 @@ namespace OpenMS } // spectrum type (profile, centroid or automatic) - String spectrum_type = param_.getValue("average_gaussian:spectrum_type"); + std::string spectrum_type = param_.getValue("average_gaussian:spectrum_type"); if (average_type == "tophat") { - spectrum_type = param_.getValue("average_tophat:spectrum_type"); + spectrum_type = std::string(param_.getValue("average_tophat:spectrum_type")); } // parameters for Gaussian averaging @@ -493,7 +493,7 @@ namespace OpenMS void mergeSpectra_(MapType& exp, const MergeBlocks& spectra_to_merge, const UInt ms_level) { double mz_binning_width(param_.getValue("mz_binning_width")); - String mz_binning_unit(param_.getValue("mz_binning_width_unit")); + std::string mz_binning_unit(param_.getValue("mz_binning_width_unit")); // merge spectra MapType merged_spectra; @@ -694,7 +694,7 @@ namespace OpenMS MapType exp_tmp; // temporary experiment for averaged spectra double mz_binning_width(param_.getValue("mz_binning_width")); - String mz_binning_unit(param_.getValue("mz_binning_width_unit")); + std::string mz_binning_unit(param_.getValue("mz_binning_width_unit")); unsigned progress = 0; std::stringstream progress_message; @@ -807,7 +807,7 @@ namespace OpenMS MapType exp_tmp; // temporary experiment for averaged spectra double mz_binning_width(param_.getValue("mz_binning_width")); - String mz_binning_unit(param_.getValue("mz_binning_width_unit")); + std::string mz_binning_unit(param_.getValue("mz_binning_width_unit")); unsigned progress = 0; ProgressLogger logger; diff --git a/src/openms/include/OpenMS/FORMAT/FASTAFile.h b/src/openms/include/OpenMS/FORMAT/FASTAFile.h index bb314c4a762..46f649d6f4e 100644 --- a/src/openms/include/OpenMS/FORMAT/FASTAFile.h +++ b/src/openms/include/OpenMS/FORMAT/FASTAFile.h @@ -36,11 +36,11 @@ #include #include +#include -#include +#include // for std::function #include -#include -#include +#include // for unique_ptr #include namespace OpenMS @@ -61,7 +61,7 @@ namespace OpenMS */ - class OPENMS_DLLAPI FASTAFile + class OPENMS_DLLAPI FASTAFile : public ProgressLogger { public: /** @@ -197,12 +197,12 @@ namespace OpenMS /** @brief loads a FASTA file given by 'filename' and stores the information in 'data' - This uses more RAM than readStart() and readNext(). + This uses more RAM than readStart() and readNext(), but supports progress-logging. @exception Exception::FileNotFound is thrown if the file does not exists. @exception Exception::ParseError is thrown if the file does not suit to the standard. */ - void static load(const String& filename, std::vector& data); + void load(const String& filename, std::vector& data) const; /** @brief stores the data given by 'data' at the file 'filename' @@ -211,7 +211,7 @@ namespace OpenMS @exception Exception::UnableToCreateFile is thrown if the process is not able to write the file. */ - void static store(const String& filename, const std::vector& data); + void store(const String& filename, const std::vector& data) const; protected: std::fstream infile_; ///< filestream for reading; init using FastaFile::readStart() diff --git a/src/openms/include/OpenMS/FORMAT/FileHandler.h b/src/openms/include/OpenMS/FORMAT/FileHandler.h index 0ceb10af2f1..e594a264eaa 100644 --- a/src/openms/include/OpenMS/FORMAT/FileHandler.h +++ b/src/openms/include/OpenMS/FORMAT/FileHandler.h @@ -103,6 +103,22 @@ namespace OpenMS */ static String swapExtension(const String& filename, const FileTypes::Type new_type); + + /** + @brief Useful function for TOPP tools which have an 'out_type' parameter and want to know what + output format to write. + This function makes sure that the type derived from @p output_filename and @p requested_type are consistent, i.e. + are either identical or one of them is UNKNOWN. Upon conflict, an error message is printed and the UNKNOWN type is returned. + + @param output_filename A full filename (with none, absolute or relative paths) whose type is + determined using FileHandler::getTypeByFileName() internally + @param requested_type A type as string, usually obtained from '-out_type', e.g. "FASTA" (case insensitive). + The string can be empty (yields UNKNOWN for this type) + @return A consistent file type or UNKNOWN upon conflict + */ + static FileTypes::Type getConsistentOutputfileType(const String& output_filename, const String& requested_type); + + /** @brief Determines the file type of a file by parsing the first few lines diff --git a/src/openms/include/OpenMS/FORMAT/FileTypes.h b/src/openms/include/OpenMS/FORMAT/FileTypes.h index 34f4c70a035..d4580292681 100644 --- a/src/openms/include/OpenMS/FORMAT/FileTypes.h +++ b/src/openms/include/OpenMS/FORMAT/FileTypes.h @@ -156,7 +156,8 @@ namespace OpenMS /// MZML becomes "mzML raw data file", but FEATUREXML becomes "OpenMS feature map" static String typeToDescription(Type type); - /// Converts a file type name into a Type + /// Converts a file type name into a Type + /// @param name A case-insensitive name (e.g. FASTA or Fasta, etc.) static Type nameToType(const String& name); /// Returns the mzML name (TODO: switch to accession since they are more stable!) diff --git a/src/openms/include/OpenMS/FORMAT/HANDLERS/IndexedMzMLHandler.h b/src/openms/include/OpenMS/FORMAT/HANDLERS/IndexedMzMLHandler.h index e202f7011b4..def66560b6e 100644 --- a/src/openms/include/OpenMS/FORMAT/HANDLERS/IndexedMzMLHandler.h +++ b/src/openms/include/OpenMS/FORMAT/HANDLERS/IndexedMzMLHandler.h @@ -107,7 +107,7 @@ namespace Internal @note You *need* to check getParsingSuccess after calling this! */ - void parseFooter_(String filename); + void parseFooter_(); std::string getChromatogramById_helper_(int id); @@ -138,7 +138,7 @@ namespace Internal Tries to parse the file, success can be checked with getParsingSuccess() */ - void openFile(String filename); + void openFile(const String& filename); /** @brief Returns whether parsing was successful @@ -228,7 +228,7 @@ namespace Internal @param id The chromatogram native id @param s The chromatogram to be used and filled with data */ - void getMSChromatogramByNativeId(std::string id, OpenMS::MSChromatogram& c); + void getMSChromatogramByNativeId(const std::string& id, OpenMS::MSChromatogram& c); /** @brief Retrieve the raw data for the chromatogram at position "id" diff --git a/src/openms/include/OpenMS/FORMAT/HANDLERS/ParamXMLHandler.h b/src/openms/include/OpenMS/FORMAT/HANDLERS/ParamXMLHandler.h index 91ba5f795c4..4b7f26faf9b 100644 --- a/src/openms/include/OpenMS/FORMAT/HANDLERS/ParamXMLHandler.h +++ b/src/openms/include/OpenMS/FORMAT/HANDLERS/ParamXMLHandler.h @@ -76,10 +76,10 @@ namespace OpenMS { String name; String type; - StringList stringlist; + std::vector stringlist; IntList intlist; DoubleList doublelist; - StringList tags; + std::vector tags; String description; String restrictions; Int restrictions_index; diff --git a/src/openms/include/OpenMS/FORMAT/MzQCFile.h b/src/openms/include/OpenMS/FORMAT/MzQCFile.h index 2829f529821..d932797a520 100644 --- a/src/openms/include/OpenMS/FORMAT/MzQCFile.h +++ b/src/openms/include/OpenMS/FORMAT/MzQCFile.h @@ -50,24 +50,22 @@ namespace OpenMS // Default constructor MzQCFile() = default; - // Store the mzQC file /** @brief Stores QC data in mzQC file with JSON format - @param inputFileName mzML input file name - @param outputFileName mzQC output file name + @param input_file mzML input file name + @param output_file mzQC output file name @param exp MSExperiment to extract QC data from, prior sortSpectra() and updateRanges() required - @param contactName name of the person creating the mzQC file - @param contactAddress contact address (mail/e-mail or phone) of the person creating the mzQC file + @param contact_name name of the person creating the mzQC file + @param contact_address contact address (mail/e-mail or phone) of the person creating the mzQC file @param description description and comments about the mzQC file contents @param label unique and informative label for the run */ - void store(const String & inputFileName, - const String & outputFileName, - const MSExperiment & exp, - const String & contactName, - const String & contactAddress, - const String & description, - const String & label) const; - + void store(const String& input_file, + const String& output_file, + const MSExperiment& exp, + const String& contact_name, + const String& contact_address, + const String& description, + const String& label) const; }; } \ No newline at end of file diff --git a/src/openms/include/OpenMS/FORMAT/QcMLFile.h b/src/openms/include/OpenMS/FORMAT/QcMLFile.h index 64666ea4757..46d49d5b8d0 100644 --- a/src/openms/include/OpenMS/FORMAT/QcMLFile.h +++ b/src/openms/include/OpenMS/FORMAT/QcMLFile.h @@ -41,6 +41,7 @@ #include + #include #include #include diff --git a/src/openms/include/OpenMS/IONMOBILITY/FAIMSHelper.h b/src/openms/include/OpenMS/IONMOBILITY/FAIMSHelper.h new file mode 100644 index 00000000000..4e2252b706a --- /dev/null +++ b/src/openms/include/OpenMS/IONMOBILITY/FAIMSHelper.h @@ -0,0 +1,65 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: Eugen Netz $ +// $Authors: Eugen Netz $ +// -------------------------------------------------------------------------- + +#pragma once + +#include +#include + +namespace OpenMS +{ + + /** + @brief Helper functions for FAIMS data + + FAIMSHelper contains convenience functions to deal with FAIMS + compensation voltages and related data. + + */ + class OPENMS_DLLAPI FAIMSHelper + { + public: + virtual ~FAIMSHelper() {} + + /** + @brief Get all FAIMS compensation voltages that occur in a PeakMap + + If the data is not FAIMS, an empty set will be returned. + + @param exp The PeakMap with FAIMS data + */ + static std::set getCompensationVoltages(const PeakMap& exp); + }; + +} //end namespace OpenMS diff --git a/src/openms/include/OpenMS/IONMOBILITY/MSRunIMSplitter.h b/src/openms/include/OpenMS/IONMOBILITY/MSRunIMSplitter.h new file mode 100644 index 00000000000..44b29b1b40a --- /dev/null +++ b/src/openms/include/OpenMS/IONMOBILITY/MSRunIMSplitter.h @@ -0,0 +1,68 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: Eugen Netz $ +// $Authors: Eugen Netz $ +// -------------------------------------------------------------------------- + +#pragma once + +#include +#include + +namespace OpenMS +{ + + /** + @brief This class splits PeakMaps by IM values + + Contains a function to split a PeakMap by FAIMS compensation voltages. + */ + class OPENMS_DLLAPI MSRunIMSplitter + { + public: + virtual ~MSRunIMSplitter() {} + + /** + @brief Splits a PeakMap into one PeakMap per FAIMS CV value + + This only works with a PeakMap that has a FAIMS compensation voltage + associated with each spectrum. + The spectra from the original PeakMap are moved to new PeakMaps, + so the original PeakMap is unusable afterwards. + + @param exp The PeakMap + @return Several maps, split by CVs + @throws Exception::MissingInformation if @p exp is not FAIMS data + */ + static std::vector splitByFAIMSCV(PeakMap&& exp); + }; + +} //end namespace OpenMS diff --git a/src/openms/include/OpenMS/IONMOBILITY/sources.cmake b/src/openms/include/OpenMS/IONMOBILITY/sources.cmake new file mode 100644 index 00000000000..cb742da2dd5 --- /dev/null +++ b/src/openms/include/OpenMS/IONMOBILITY/sources.cmake @@ -0,0 +1,19 @@ +### the directory name +set(directory include/OpenMS/IONMOBILITY) + +### list all header files of the directory here +set(sources_list_h +FAIMSHelper.h +MSRunIMSplitter.h +) + +### add path to the filenames +set(sources_h) +foreach(i ${sources_list_h}) + list(APPEND sources_h ${directory}/${i}) +endforeach(i) + +### source group definition +source_group("Header Files\\OpenMS\\IONMOBILITY" FILES ${sources_h}) + +set(OpenMS_sources_h ${OpenMS_sources_h} ${sources_h}) diff --git a/src/openms/include/OpenMS/KERNEL/OnDiscMSExperiment.h b/src/openms/include/OpenMS/KERNEL/OnDiscMSExperiment.h index 3bf059ddc83..e69295a1a85 100644 --- a/src/openms/include/OpenMS/KERNEL/OnDiscMSExperiment.h +++ b/src/openms/include/OpenMS/KERNEL/OnDiscMSExperiment.h @@ -157,7 +157,7 @@ namespace OpenMS /// returns whether spectra are empty inline bool empty() const { - return indexed_mzml_file_.getNrSpectra() == 0; + return getNrSpectra() == 0; } /// get the total number of spectra available diff --git a/src/openms/include/OpenMS/MATH/STATISTICS/PosteriorErrorProbabilityModel.h b/src/openms/include/OpenMS/MATH/STATISTICS/PosteriorErrorProbabilityModel.h index dac0719d474..8ec310bf6d7 100644 --- a/src/openms/include/OpenMS/MATH/STATISTICS/PosteriorErrorProbabilityModel.h +++ b/src/openms/include/OpenMS/MATH/STATISTICS/PosteriorErrorProbabilityModel.h @@ -35,10 +35,11 @@ #pragma once #include +#include +#include #include #include #include -#include #include #include @@ -265,7 +266,7 @@ namespace OpenMS /// @requested_score_types the requested score_types in order of preference (will be tested with a "_score" suffix as well) /// @hit the PeptideHit to extract from /// @actual_score_type the current score type to take preference if matching - static double getScore_(const StringList& requested_score_types, const PeptideHit & hit, const String& actual_score_type); + static double getScore_(const std::vector& requested_score_types, const PeptideHit & hit, const String& actual_score_type); /// assignment operator (not implemented) PosteriorErrorProbabilityModel & operator=(const PosteriorErrorProbabilityModel & rhs); diff --git a/src/openms/include/OpenMS/QC/FWHM.h b/src/openms/include/OpenMS/QC/FWHM.h index 9637465b339..80151128112 100644 --- a/src/openms/include/OpenMS/QC/FWHM.h +++ b/src/openms/include/OpenMS/QC/FWHM.h @@ -61,11 +61,11 @@ namespace OpenMS virtual ~FWHM() = default; /** - @brief Moves FWHM metavalues from the feature to all its PeptideIdentifications (since that's were mzTab takes it from if we want to preserve Raw file origin) + @brief Moves FWHM metavalues from the feature to all its PeptideIdentifications (since that's were mzTab takes it from if we want to preserve Raw file origin) - A warning is issues on the commandline if a feature does not have either 'FWHM' or 'model_FWHM' as metavalue. + A warning is issued on the commandline if a feature does not have either 'FWHM' or 'model_FWHM' as metavalue. - @param features FeatureMap with metavalue 'FWHM' or 'model_FWHM' + @param features FeatureMap with features which have metavalue 'FWHM' or 'model_FWHM' **/ void compute(FeatureMap& features); diff --git a/src/openms/include/OpenMS/QC/SpectrumCount.h b/src/openms/include/OpenMS/QC/SpectrumCount.h new file mode 100644 index 00000000000..6d28433cfdc --- /dev/null +++ b/src/openms/include/OpenMS/QC/SpectrumCount.h @@ -0,0 +1,72 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARSpectrumCountULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: Axel Walter $ +// $Authors: Axel Walter $ +// -------------------------------------------------------------------------- + +#pragma once + +#include + +/** + * @brief Number of MS spectra per MS level (SpectrumCount) as a QC metric + */ + +namespace OpenMS +{ + class MSExperiment; + + class OPENMS_DLLAPI SpectrumCount : public QCBase + { + public: + /// Constructor + SpectrumCount() = default; + + /// Destructor + virtual ~SpectrumCount() = default; + + /** + @brief Compute number of spectra per MS level and returns them in a map + + @param exp MSExperiment containing the spectra to be counted + @return SpectrumCount + **/ + + std::map compute(const MSExperiment& exp); + + const String& getName() const override; + + QCBase::Status requires() const override; + + private: + const String name_ = "SpectrumCount"; + }; +} diff --git a/src/openms/include/OpenMS/QC/TIC.h b/src/openms/include/OpenMS/QC/TIC.h index 601e92c6687..6b71f20d9e5 100644 --- a/src/openms/include/OpenMS/QC/TIC.h +++ b/src/openms/include/OpenMS/QC/TIC.h @@ -60,8 +60,20 @@ namespace OpenMS /// Destructor virtual ~TIC() = default; - void clear(); + // stores TIC values calculated by compute function + struct OPENMS_DLLAPI Result + { + std::vector intensities; // TIC intensities + std::vector retention_times; // TIC RTs in seconds + UInt area = 0; // Area under TIC + UInt fall = 0; // MS1 signal fall (10x) count + UInt jump = 0; // MS1 signal jump (10x) count + + bool operator==(const Result& rhs) const; + }; + + /** @brief Compute Total Ion Count and applies the resampling algorithm, if a bin size in RT seconds greater than 0 is given. @@ -69,9 +81,10 @@ namespace OpenMS @param exp Peak map to compute the MS1 tick from @param bin_size RT bin size in seconds - @return TIC Chromatogram + @return result struct with with computed QC metrics: intensities, RTs (in seconds), area under TIC, 10x MS1 signal fall, 10x MS1 signal jump + **/ - void compute(const MSExperiment &exp, float bin_size=0); + Result compute(const MSExperiment& exp, float bin_size=0); const String& getName() const override; @@ -80,10 +93,9 @@ namespace OpenMS QCBase::Status requires() const override; /// append QC data for given metrics to mzTab's MTD section - void addMetaDataMetricsToMzTab(MzTabMetaData& meta); + void addMetaDataMetricsToMzTab(MzTabMetaData& meta, std::vector& tics); private: const String name_ = "TIC"; - std::vector results_; }; } diff --git a/src/openms/include/OpenMS/QC/sources.cmake b/src/openms/include/OpenMS/QC/sources.cmake index 48156a4716b..2bfd2ed47d8 100644 --- a/src/openms/include/OpenMS/QC/sources.cmake +++ b/src/openms/include/OpenMS/QC/sources.cmake @@ -14,6 +14,7 @@ set(sources_list_h PSMExplainedIonCurrent.h QCBase.h RTAlignment.h + SpectrumCount.h DBSuitability.h TIC.h ) diff --git a/src/openms/include/OpenMS/SYSTEM/ExternalProcess.h b/src/openms/include/OpenMS/SYSTEM/ExternalProcess.h index db92f9667e3..d9ecb560678 100644 --- a/src/openms/include/OpenMS/SYSTEM/ExternalProcess.h +++ b/src/openms/include/OpenMS/SYSTEM/ExternalProcess.h @@ -74,6 +74,15 @@ namespace OpenMS FAILED_TO_START ///< executable not found or not enough access rights for user }; + /// Open mode for the process. + enum class IO_MODE + { + NO_IO, ///< No read nor write access + READ_ONLY, + WRITE_ONLY, + READ_WRITE + }; + /// default Ctor; callbacks for stdout/stderr are empty ExternalProcess(); @@ -94,14 +103,15 @@ namespace OpenMS @param verbose Report the call command and errors via the callbacks (default: false) @param working_dir Execute the external process in the given directory (relevant when relative input/output paths are given). Leave empty to use the current working directory. @param[out] error_string Message to display to the user if something went wrong (if return != SUCCESS) + @param io_mode Open mode for the process (read access, write access, ...) @return Did the external program succeed (SUCCESS) or did something go wrong? */ - RETURNSTATE run(const QString& exe, const QStringList& args, const QString& working_dir, const bool verbose, String& error_msg); + RETURNSTATE run(const QString& exe, const QStringList& args, const QString& working_dir, const bool verbose, String& error_msg, IO_MODE io_mode = IO_MODE::READ_WRITE); /** @brief Same as other overload, just without a returned error message */ - ExternalProcess::RETURNSTATE run(const QString& exe, const QStringList& args, const QString& working_dir, const bool verbose); + ExternalProcess::RETURNSTATE run(const QString& exe, const QStringList& args, const QString& working_dir, const bool verbose, IO_MODE io_mode = IO_MODE::READ_WRITE); private slots: void processStdOut_(); diff --git a/src/openms/include/OpenMS/SYSTEM/File.h b/src/openms/include/OpenMS/SYSTEM/File.h index b28abcba864..51c06856e5f 100644 --- a/src/openms/include/OpenMS/SYSTEM/File.h +++ b/src/openms/include/OpenMS/SYSTEM/File.h @@ -37,6 +37,7 @@ #include #include #include +#include namespace OpenMS @@ -352,6 +353,7 @@ namespace OpenMS TemporaryFiles_(const TemporaryFiles_&) = delete; // copy is forbidden TemporaryFiles_& operator=(const TemporaryFiles_&) = delete; StringList filenames_; + std::mutex mtx_; }; diff --git a/src/openms/include/OpenMS/TRANSFORMATIONS/FEATUREFINDER/LevMarqFitter1D.h b/src/openms/include/OpenMS/TRANSFORMATIONS/FEATUREFINDER/LevMarqFitter1D.h index 86b06cd8971..aa9a080ef95 100644 --- a/src/openms/include/OpenMS/TRANSFORMATIONS/FEATUREFINDER/LevMarqFitter1D.h +++ b/src/openms/include/OpenMS/TRANSFORMATIONS/FEATUREFINDER/LevMarqFitter1D.h @@ -82,7 +82,7 @@ namespace OpenMS LevMarqFitter1D() : Fitter1D() { - this->defaults_.setValue("max_iteration", 500, "Maximum number of iterations using by Levenberg-Marquardt algorithm.", ListUtils::create("advanced")); + this->defaults_.setValue("max_iteration", 500, "Maximum number of iterations using by Levenberg-Marquardt algorithm.", {"advanced"}); } /// copy constructor diff --git a/src/openms/include/OpenMS/TRANSFORMATIONS/FEATUREFINDER/ProductModel.h b/src/openms/include/OpenMS/TRANSFORMATIONS/FEATUREFINDER/ProductModel.h index 58edf7207d3..1d19fd8c9a2 100644 --- a/src/openms/include/OpenMS/TRANSFORMATIONS/FEATUREFINDER/ProductModel.h +++ b/src/openms/include/OpenMS/TRANSFORMATIONS/FEATUREFINDER/ProductModel.h @@ -269,7 +269,7 @@ namespace OpenMS if (this->param_.exists(name)) { delete distributions_[dim]; - distributions_[dim] = Factory >::create(this->param_.getValue(name)); + distributions_[dim] = Factory >::create(this->param_.getValue(name).toString()); Param copy = this->param_.copy(name + ":", true); distributions_[dim]->setParameters(copy); if (distributions_[dim]->getName().hasSubstring("IsotopeModel")) diff --git a/src/openms/include/OpenMS/TRANSFORMATIONS/RAW2PEAK/PeakPickerIterative.h b/src/openms/include/OpenMS/TRANSFORMATIONS/RAW2PEAK/PeakPickerIterative.h index e099e701d7e..bf04a939768 100644 --- a/src/openms/include/OpenMS/TRANSFORMATIONS/RAW2PEAK/PeakPickerIterative.h +++ b/src/openms/include/OpenMS/TRANSFORMATIONS/RAW2PEAK/PeakPickerIterative.h @@ -118,19 +118,19 @@ namespace OpenMS defaults_.setValue("peak_width", 0.0, "Expected peak width half width in Dalton - peaks will be extended until this half width is reached (even if the intensitity is increasing). In conjunction with check_width_internally it will also be used to remove peaks whose spacing is larger than this value."); - defaults_.setValue("spacing_difference", 1.5, "Difference between peaks in multiples of the minimal difference to continue. The higher this value is set, the further apart peaks are allowed to be to still extend a peak. E.g. if the value is set to 1.5 and in a current peak the minimal spacing between peaks is 10 mDa, then only peaks at most 15 mDa apart will be added to the peak.", ListUtils::create("advanced")); - defaults_.setValue("sn_bin_count_", 30, "Bin count for the Signal to Noise estimation.", ListUtils::create("advanced")); - defaults_.setValue("nr_iterations_", 5, "Nr of iterations to perform (how many times the peaks are re-centered).", ListUtils::create("advanced")); + defaults_.setValue("spacing_difference", 1.5, "Difference between peaks in multiples of the minimal difference to continue. The higher this value is set, the further apart peaks are allowed to be to still extend a peak. E.g. if the value is set to 1.5 and in a current peak the minimal spacing between peaks is 10 mDa, then only peaks at most 15 mDa apart will be added to the peak.", {"advanced"}); + defaults_.setValue("sn_bin_count_", 30, "Bin count for the Signal to Noise estimation.", {"advanced"}); + defaults_.setValue("nr_iterations_", 5, "Nr of iterations to perform (how many times the peaks are re-centered).", {"advanced"}); defaults_.setMinInt("nr_iterations_", 1); - defaults_.setValue("sn_win_len_", 20.0, "Window length for the Signal to Noise estimation.", ListUtils::create("advanced")); + defaults_.setValue("sn_win_len_", 20.0, "Window length for the Signal to Noise estimation.", {"advanced"}); - defaults_.setValue("check_width_internally", "false", "Delete peaks where the spacing is larger than the peak width (should be set to true to avoid artefacts)", ListUtils::create("advanced")); - defaults_.setValidStrings("check_width_internally", ListUtils::create("true,false")); + defaults_.setValue("check_width_internally", "false", "Delete peaks where the spacing is larger than the peak width (should be set to true to avoid artefacts)", {"advanced"}); + defaults_.setValidStrings("check_width_internally", {"true","false"}); defaults_.setValue("ms1_only", "false", "Only do MS1"); - defaults_.setValidStrings("ms1_only", ListUtils::create("true,false")); + defaults_.setValidStrings("ms1_only", {"true","false"}); defaults_.setValue("clear_meta_data", "false", "Delete meta data about peak width"); - defaults_.setValidStrings("clear_meta_data", ListUtils::create("true,false")); + defaults_.setValidStrings("clear_meta_data", {"true","false"}); // write defaults into Param object param_ defaultsToParam_(); diff --git a/src/openms/include/OpenMS/TRANSFORMATIONS/RAW2PEAK/TwoDOptimization.h b/src/openms/include/OpenMS/TRANSFORMATIONS/RAW2PEAK/TwoDOptimization.h index b2f55cb6420..bc08f3d0691 100644 --- a/src/openms/include/OpenMS/TRANSFORMATIONS/RAW2PEAK/TwoDOptimization.h +++ b/src/openms/include/OpenMS/TRANSFORMATIONS/RAW2PEAK/TwoDOptimization.h @@ -744,23 +744,23 @@ namespace OpenMS struct OpenMS::OptimizationFunctions::PenaltyFactors penalties; - DataValue dv = param_.getValue("penalties:position"); - if (dv.isEmpty() || dv.toString() == "") + ParamValue pv = param_.getValue("penalties:position"); + if (pv.isEmpty() || pv.toString() == "") penalties.pos = 0.; else - penalties.pos = (float)dv; + penalties.pos = (float)pv; - dv = param_.getValue("penalties:left_width"); - if (dv.isEmpty() || dv.toString() == "") + pv = param_.getValue("penalties:left_width"); + if (pv.isEmpty() || pv.toString() == "") penalties.lWidth = 1.; else - penalties.lWidth = (float)dv; + penalties.lWidth = (float)pv; - dv = param_.getValue("penalties:right_width"); - if (dv.isEmpty() || dv.toString() == "") + pv = param_.getValue("penalties:right_width"); + if (pv.isEmpty() || pv.toString() == "") penalties.rWidth = 1.; else - penalties.rWidth = (float)dv; + penalties.rWidth = (float)pv; #ifdef DEBUG_2D std::cout << penalties.pos << " " << penalties.rWidth << " " @@ -776,11 +776,11 @@ namespace OpenMS // std::cout << "---------------------------------------------------------------\n\n\n\n"; UInt max_iteration; - dv = param_.getValue("iterations"); - if (dv.isEmpty() || dv.toString() == "") + pv = param_.getValue("iterations"); + if (pv.isEmpty() || pv.toString() == "") max_iteration = 15; else - max_iteration = (UInt)dv; + max_iteration = (UInt)pv; std::vector peak_shapes; diff --git a/src/openms/includes.cmake b/src/openms/includes.cmake index efc8464a49e..4f5376dbf3a 100644 --- a/src/openms/includes.cmake +++ b/src/openms/includes.cmake @@ -20,6 +20,7 @@ include(source/FORMAT/HANDLERS/sources.cmake) include(source/FORMAT/VALIDATORS/sources.cmake) include(source/FORMAT/OPTIONS/sources.cmake) include(source/FORMAT/sources.cmake) +include(source/IONMOBILITY/sources.cmake) include(source/ANALYSIS/QUANTITATION/sources.cmake) include(source/ANALYSIS/SVM/sources.cmake) include(source/ANALYSIS/MAPMATCHING/sources.cmake) @@ -74,6 +75,7 @@ include(include/OpenMS/FORMAT/DATAACCESS/sources.cmake) include(include/OpenMS/FORMAT/HANDLERS/sources.cmake) include(include/OpenMS/FORMAT/VALIDATORS/sources.cmake) include(include/OpenMS/FORMAT/OPTIONS/sources.cmake) +include(include/OpenMS/IONMOBILITY/sources.cmake) include(include/OpenMS/ANALYSIS/DECHARGING/sources.cmake) include(include/OpenMS/ANALYSIS/ID/sources.cmake) diff --git a/src/openms/source/ANALYSIS/DECHARGING/FeatureDeconvolution.cpp b/src/openms/source/ANALYSIS/DECHARGING/FeatureDeconvolution.cpp index 2c9d79298d2..75aa5143c6d 100644 --- a/src/openms/source/ANALYSIS/DECHARGING/FeatureDeconvolution.cpp +++ b/src/openms/source/ANALYSIS/DECHARGING/FeatureDeconvolution.cpp @@ -115,14 +115,14 @@ namespace OpenMS defaults_.setMinInt("charge_span_max", 1); // will only find adduct variants of the same charge defaults_.setValue("q_try", "feature", "Try different values of charge for each feature according to the above settings ('heuristic' [does not test all charges, just the likely ones] or 'all' ), or leave feature charge untouched ('feature')."); - defaults_.setValidStrings("q_try", ListUtils::create("feature,heuristic,all")); + defaults_.setValidStrings("q_try", {"feature","heuristic","all"}); defaults_.setValue("retention_max_diff", 1.0, "Maximum allowed RT difference between any two features if their relation shall be determined"); defaults_.setValue("retention_max_diff_local", 1.0, "Maximum allowed RT difference between between two co-features, after adduct shifts have been accounted for (if you do not have any adduct shifts, this value should be equal to 'retention_max_diff', otherwise it should be smaller!)"); defaults_.setValue("mass_max_diff", 0.5, "Maximum allowed mass difference [in Th] for a single feature."); // Na+:0.1 , (2)H4H-4:0.1:-2:heavy - defaults_.setValue("potential_adducts", ListUtils::create("K:+:0.1"), "Adducts used to explain mass differences in format: 'Element:Charge(+/-):Probability[:RTShift[:Label]]', i.e. the number of '+' or '-' indicate the charge, e.g. 'Ca:++:0.5' indicates +2. Probabilites have to be in (0,1]. RTShift param is optional and indicates the expected RT shift caused by this adduct, e.g. '(2)H4H-4:0:1:-3' indicates a 4 deuterium label, which causes early elution by 3 seconds. As a fifth parameter you can add a label which is tagged on every feature which has this adduct. This also determines the map number in the consensus file."); + defaults_.setValue("potential_adducts", std::vector{"K:+:0.1"}, "Adducts used to explain mass differences in format: 'Element:Charge(+/-):Probability[:RTShift[:Label]]', i.e. the number of '+' or '-' indicate the charge, e.g. 'Ca:++:0.5' indicates +2. Probabilites have to be in (0,1]. RTShift param is optional and indicates the expected RT shift caused by this adduct, e.g. '(2)H4H-4:0:1:-3' indicates a 4 deuterium label, which causes early elution by 3 seconds. As a fifth parameter you can add a label which is tagged on every feature which has this adduct. This also determines the map number in the consensus file."); defaults_.setValue("max_neutrals", 0, "Maximal number of neutral adducts(q=0) allowed. Add them in the 'potential_adducts' section!"); defaults_.setValue("max_minority_bound", 2, "Maximum count of the least probable adduct (according to 'potential_adducts' param) within a charge variant. E.g. setting this to 2 will not allow an adduct composition of '1(H+),3(Na+)' if Na+ is the least probable adduct"); @@ -133,13 +133,13 @@ namespace OpenMS defaults_.setMaxFloat("min_rt_overlap", 1); defaults_.setValue("intensity_filter", "false", "Enable the intensity filter, which will only allow edges between two equally charged features if the intensity of the feature with less likely adducts is smaller than that of the other feature. It is not used for features of different charge."); - defaults_.setValidStrings("intensity_filter", ListUtils::create("true,false")); + defaults_.setValidStrings("intensity_filter", {"true","false"}); defaults_.setValue("negative_mode", "false", "Enable negative ionization mode."); - defaults_.setValue("default_map_label", "decharged features", "Label of map in output consensus file where all features are put by default", ListUtils::create("advanced")); + defaults_.setValue("default_map_label", "decharged features", "Label of map in output consensus file where all features are put by default", {"advanced"}); - defaults_.setValue("verbose_level", 0, "Amount of debug information given during processing.", ListUtils::create("advanced")); + defaults_.setValue("verbose_level", 0, "Amount of debug information given during processing.", {"advanced"}); defaults_.setMinInt("verbose_level", 0); defaults_.setMaxInt("verbose_level", 3); @@ -150,8 +150,8 @@ namespace OpenMS { map_label_.clear(); map_label_inverse_.clear(); - map_label_inverse_[param_.getValue("default_map_label")] = 0; // default virtual map (for unlabeled experiments) - map_label_[0] = param_.getValue("default_map_label"); + map_label_inverse_[String(param_.getValue("default_map_label").toString())] = 0; // default virtual map (for unlabeled experiments) + map_label_[0] = String(param_.getValue("default_map_label").toString()); if (param_.getValue("q_try") == "feature") q_try_ = QFROMFEATURE; @@ -161,7 +161,7 @@ namespace OpenMS q_try_ = QALL; - StringList potential_adducts_s = param_.getValue("potential_adducts"); + StringList potential_adducts_s = ListUtils::toStringList(param_.getValue("potential_adducts")); potential_adducts_.clear(); bool had_nonzero_RT = false; // adducts with RT-shift > 0 ? diff --git a/src/openms/source/ANALYSIS/DECHARGING/MetaboliteFeatureDeconvolution.cpp b/src/openms/source/ANALYSIS/DECHARGING/MetaboliteFeatureDeconvolution.cpp index fee77cf3468..3e94f74e7d9 100644 --- a/src/openms/source/ANALYSIS/DECHARGING/MetaboliteFeatureDeconvolution.cpp +++ b/src/openms/source/ANALYSIS/DECHARGING/MetaboliteFeatureDeconvolution.cpp @@ -118,7 +118,7 @@ namespace OpenMS defaults_.setMinInt("charge_span_max", 1); // will only find adduct variants of the same charge defaults_.setValue("q_try", "feature", "Try different values of charge for each feature according to the above settings ('heuristic' [does not test all charges, just the likely ones] or 'all' ), or leave feature charge untouched ('feature')."); - defaults_.setValidStrings("q_try", ListUtils::create("feature,heuristic,all")); + defaults_.setValidStrings("q_try", {"feature","heuristic","all"}); defaults_.setValue("retention_max_diff", 1.0, "Maximum allowed RT difference between any two features if their relation shall be determined"); defaults_.setValue("retention_max_diff_local", 1.0, "Maximum allowed RT difference between between two co-features, after adduct shifts have been accounted for (if you do not have any adduct shifts, this value should be equal to 'retention_max_diff', otherwise it should be smaller!)"); @@ -126,10 +126,10 @@ namespace OpenMS defaults_.setValue("mass_max_diff", 0.05, "Maximum allowed mass tolerance per feature. Defines a symmetric tolerance window around the feature. When looking at possible feature pairs, the allowed feature-wise errors are combined for consideration of possible adduct shifts. For ppm tolerances, each window is based on the respective observed feature mz (instead of putative experimental mzs causing the observed one)!"); defaults_.setMinFloat("mass_max_diff", 0.0); defaults_.setValue("unit", "Da", "Unit of the 'max_difference' parameter"); - defaults_.setValidStrings("unit", ListUtils::create("Da,ppm")); + defaults_.setValidStrings("unit", {"Da","ppm"}); // Na+:0.1 , (2)H4H-4:0.1:-2:heavy - defaults_.setValue("potential_adducts", ListUtils::create("H:+:0.4,Na:+:0.25,NH4:+:0.25,K:+:0.1,H-2O-1:0:0.05"), "Adducts used to explain mass differences in format: 'Elements:Charge(+/-/0):Probability[:RTShift[:Label]]', i.e. the number of '+' or '-' indicate the charge ('0' if neutral adduct), e.g. 'Ca:++:0.5' indicates +2. Probabilites have to be in (0,1]. The optional RTShift param indicates the expected RT shift caused by this adduct, e.g. '(2)H4H-4:0:1:-3' indicates a 4 deuterium label, which causes early elution by 3 seconds. As fifth parameter you can add a label for every feature with this adduct. This also determines the map number in the consensus file. Adduct element losses are written in the form 'H-2'. All provided adducts need to have the same charge sign or be neutral! Mixing of adducts with different charge directions is only allowed as neutral complexes. For example, 'H-1Na:0:0.05' can be used to model Sodium gains (with balancing deprotonation) in negative mode."); + defaults_.setValue("potential_adducts", std::vector{"H:+:0.4","Na:+:0.25","NH4:+:0.25","K:+:0.1","H-2O-1:0:0.05"}, "Adducts used to explain mass differences in format: 'Elements:Charge(+/-/0):Probability[:RTShift[:Label]]', i.e. the number of '+' or '-' indicate the charge ('0' if neutral adduct), e.g. 'Ca:++:0.5' indicates +2. Probabilites have to be in (0,1]. The optional RTShift param indicates the expected RT shift caused by this adduct, e.g. '(2)H4H-4:0:1:-3' indicates a 4 deuterium label, which causes early elution by 3 seconds. As fifth parameter you can add a label for every feature with this adduct. This also determines the map number in the consensus file. Adduct element losses are written in the form 'H-2'. All provided adducts need to have the same charge sign or be neutral! Mixing of adducts with different charge directions is only allowed as neutral complexes. For example, 'H-1Na:0:0.05' can be used to model Sodium gains (with balancing deprotonation) in negative mode."); defaults_.setValue("max_neutrals", 1, "Maximal number of neutral adducts(q=0) allowed. Add them in the 'potential_adducts' section!"); defaults_.setValue("use_minority_bound", "true", "Prune the considered adduct transitions by transition probabilities."); @@ -141,13 +141,13 @@ namespace OpenMS defaults_.setMaxFloat("min_rt_overlap", 1); defaults_.setValue("intensity_filter", "false", "Enable the intensity filter, which will only allow edges between two equally charged features if the intensity of the feature with less likely adducts is smaller than that of the other feature. It is not used for features of different charge."); - defaults_.setValidStrings("intensity_filter", ListUtils::create("true,false")); + defaults_.setValidStrings("intensity_filter", {"true","false"}); defaults_.setValue("negative_mode", "false", "Enable negative ionization mode."); - defaults_.setValue("default_map_label", "decharged features", "Label of map in output consensus file where all features are put by default", ListUtils::create("advanced")); + defaults_.setValue("default_map_label", "decharged features", "Label of map in output consensus file where all features are put by default", {"advanced"}); - defaults_.setValue("verbose_level", 0, "Amount of debug information given during processing.", ListUtils::create("advanced")); + defaults_.setValue("verbose_level", 0, "Amount of debug information given during processing.", {"advanced"}); defaults_.setMinInt("verbose_level", 0); defaults_.setMaxInt("verbose_level", 3); @@ -158,8 +158,8 @@ namespace OpenMS { map_label_.clear(); map_label_inverse_.clear(); - map_label_inverse_[param_.getValue("default_map_label")] = 0; // default virtual map (for unlabeled experiments) - map_label_[0] = param_.getValue("default_map_label"); + map_label_inverse_[param_.getValue("default_map_label").toString()] = 0; // default virtual map (for unlabeled experiments) + map_label_[0] = param_.getValue("default_map_label").toString(); if (param_.getValue("q_try") == "feature") q_try_ = QFROMFEATURE; @@ -169,7 +169,7 @@ namespace OpenMS q_try_ = QALL; - StringList potential_adducts_s = param_.getValue("potential_adducts"); + StringList potential_adducts_s = ListUtils::toStringList(param_.getValue("potential_adducts")); potential_adducts_.clear(); bool had_nonzero_RT = false; // adducts with RT-shift > 0 ? @@ -543,7 +543,7 @@ namespace OpenMS } else { - throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "WARNING! Invalid tolerance unit! " + String(param_.getValue("unit")) + "\n"); + throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "WARNING! Invalid tolerance unit! " + param_.getValue("unit").toString() + "\n"); } //abs charge "3" to abs charge "1" -> simply invert charge delta for negative case? diff --git a/src/openms/source/ANALYSIS/DENOVO/CompNovoIdentificationBase.cpp b/src/openms/source/ANALYSIS/DENOVO/CompNovoIdentificationBase.cpp index d20672734d3..5457aeb1618 100644 --- a/src/openms/source/ANALYSIS/DENOVO/CompNovoIdentificationBase.cpp +++ b/src/openms/source/ANALYSIS/DENOVO/CompNovoIdentificationBase.cpp @@ -60,37 +60,37 @@ namespace OpenMS max_subscore_number_(30), max_isotope_(3) { - defaults_.setValue("max_number_aa_per_decomp", 4, "maximal amino acid frequency per decomposition", ListUtils::create("advanced")); + defaults_.setValue("max_number_aa_per_decomp", 4, "maximal amino acid frequency per decomposition", {"advanced"}); defaults_.setValue("tryptic_only", "true", "if set to true only tryptic peptides are reported"); defaults_.setValue("precursor_mass_tolerance", 1.5, "precursor mass tolerance"); defaults_.setValue("fragment_mass_tolerance", 0.3, "fragment mass tolerance"); - defaults_.setValue("max_number_pivot", 9, "maximal number of pivot ions to be used", ListUtils::create("advanced")); - defaults_.setValue("max_subscore_number", 40, "maximal number of solutions of a subsegment that are kept", ListUtils::create("advanced")); - defaults_.setValue("decomp_weights_precision", 0.01, "precision used to calculate the decompositions, this only affects cache usage!", ListUtils::create("advanced")); - defaults_.setValue("double_charged_iso_threshold", 0.6, "minimal isotope intensity correlation of doubly charged ions to be used to score the single scored ions", ListUtils::create("advanced")); + defaults_.setValue("max_number_pivot", 9, "maximal number of pivot ions to be used", {"advanced"}); + defaults_.setValue("max_subscore_number", 40, "maximal number of solutions of a subsegment that are kept", {"advanced"}); + defaults_.setValue("decomp_weights_precision", 0.01, "precision used to calculate the decompositions, this only affects cache usage!", {"advanced"}); + defaults_.setValue("double_charged_iso_threshold", 0.6, "minimal isotope intensity correlation of doubly charged ions to be used to score the single scored ions", {"advanced"}); defaults_.setValue("max_mz", 2000.0, "maximal m/z value used to calculate isotope distributions"); defaults_.setValue("min_mz", 200.0, "minimal m/z value used to calculate the isotope distributions"); - defaults_.setValue("max_isotope_to_score", 3, "max isotope peak to be considered in the scoring", ListUtils::create("advanced")); - defaults_.setValue("max_decomp_weight", 450.0, "maximal m/z difference used to calculate the decompositions", ListUtils::create("advanced")); - defaults_.setValue("max_isotope", 3, "max isotope used in the theoretical spectra to score", ListUtils::create("advanced")); + defaults_.setValue("max_isotope_to_score", 3, "max isotope peak to be considered in the scoring", {"advanced"}); + defaults_.setValue("max_decomp_weight", 450.0, "maximal m/z difference used to calculate the decompositions", {"advanced"}); + defaults_.setValue("max_isotope", 3, "max isotope used in the theoretical spectra to score", {"advanced"}); defaults_.setValue("missed_cleavages", 1, "maximal number of missed cleavages allowed per peptide"); defaults_.setValue("number_of_hits", 100, "maximal number of hits which are reported per spectrum"); defaults_.setValue("estimate_precursor_mz", "true", "If set to true, the precursor charge will be estimated, e.g. from the precursor peaks of the ETD spectrum.\n" "The input is believed otherwise."); - defaults_.setValidStrings("estimate_precursor_mz", ListUtils::create("true,false")); - defaults_.setValue("number_of_prescoring_hits", 250, "how many sequences are kept after first rough scoring for better scoring", ListUtils::create("advanced")); + defaults_.setValidStrings("estimate_precursor_mz", {"true","false"}); + defaults_.setValue("number_of_prescoring_hits", 250, "how many sequences are kept after first rough scoring for better scoring", {"advanced"}); // set all known modifications as restriction vector all_mods; ModificationsDB::getInstance()->getAllSearchModifications(all_mods); - defaults_.setValue("fixed_modifications", ListUtils::create(""), "fixed modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)' or 'Oxidation (M)'"); - defaults_.setValidStrings("fixed_modifications", all_mods); + defaults_.setValue("fixed_modifications", std::vector(), "fixed modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)' or 'Oxidation (M)'"); + defaults_.setValidStrings("fixed_modifications", ListUtils::create(all_mods)); - defaults_.setValue("variable_modifications", ListUtils::create(""), "variable modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)' or 'Oxidation (M)'"); - defaults_.setValidStrings("variable_modifications", all_mods); + defaults_.setValue("variable_modifications", std::vector(), "variable modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)' or 'Oxidation (M)'"); + defaults_.setValidStrings("variable_modifications", ListUtils::create(all_mods)); - defaults_.setValue("residue_set", "Natural19WithoutI", "The predefined amino acid set that should be used, see doc of ResidueDB for possible residue sets", ListUtils::create("advanced")); + defaults_.setValue("residue_set", "Natural19WithoutI", "The predefined amino acid set that should be used, see doc of ResidueDB for possible residue sets", {"advanced"}); defaultsToParam_(); } @@ -626,7 +626,7 @@ for (set::const_iterator it = used_pos.begin(); it != used_pos.end(); ++it void CompNovoIdentificationBase::updateMembers_() { // init residue mass table - String residue_set(param_.getValue("residue_set")); + String residue_set(param_.getValue("residue_set").toString()); set residues = ResidueDB::getInstance()->getResidues(residue_set); for (set::const_iterator it = residues.begin(); it != residues.end(); ++it) @@ -649,7 +649,7 @@ for (set::const_iterator it = used_pos.begin(); it != used_pos.end(); ++it residue_to_name_.clear(); // now handle the modifications - ModificationDefinitionsSet mod_set(param_.getValue("fixed_modifications"), param_.getValue("variable_modifications")); + ModificationDefinitionsSet mod_set(ListUtils::toStringList(param_.getValue("fixed_modifications")), ListUtils::toStringList(param_.getValue("variable_modifications"))); set fixed_mods = mod_set.getFixedModifications(); for (set::const_iterator it = fixed_mods.begin(); it != fixed_mods.end(); ++it) diff --git a/src/openms/source/ANALYSIS/DENOVO/CompNovoIonScoringBase.cpp b/src/openms/source/ANALYSIS/DENOVO/CompNovoIonScoringBase.cpp index 88a9ecbc020..36c633ae1c6 100644 --- a/src/openms/source/ANALYSIS/DENOVO/CompNovoIonScoringBase.cpp +++ b/src/openms/source/ANALYSIS/DENOVO/CompNovoIonScoringBase.cpp @@ -93,13 +93,13 @@ namespace OpenMS fragment_mass_tolerance_(0) { defaults_.setValue("fragment_mass_tolerance", 0.4, "fragment mass tolerance"); - defaults_.setValue("decomp_weights_precision", 0.01, "precision used to calculate the decompositions, this only affects cache usage!", ListUtils::create("advanced")); - defaults_.setValue("double_charged_iso_threshold", 0.9, "minimal isotope intensity correlation of doubly charged ions to be used to score the single scored ions", ListUtils::create("advanced")); - defaults_.setValue("double_charged_iso_threshold_single", 0.99, "Isotope scoring threshold used for doubly charged ions to infer singly charged variants", ListUtils::create("advanced")); - defaults_.setValue("max_isotope_to_score", 3, "max isotope peak to be considered in the scoring", ListUtils::create("advanced")); - defaults_.setValue("max_decomp_weight", 600, "maximal m/z difference used to calculate the decompositions", ListUtils::create("advanced")); - defaults_.setValue("max_isotope", 3, "max isotope used in the theoretical spectra to score", ListUtils::create("advanced")); - defaults_.setValue("max_mz", 2000.0, "maximal m/z value used to calculate isotope distributions", ListUtils::create("advanced")); + defaults_.setValue("decomp_weights_precision", 0.01, "precision used to calculate the decompositions, this only affects cache usage!", {"advanced"}); + defaults_.setValue("double_charged_iso_threshold", 0.9, "minimal isotope intensity correlation of doubly charged ions to be used to score the single scored ions", {"advanced"}); + defaults_.setValue("double_charged_iso_threshold_single", 0.99, "Isotope scoring threshold used for doubly charged ions to infer singly charged variants", {"advanced"}); + defaults_.setValue("max_isotope_to_score", 3, "max isotope peak to be considered in the scoring", {"advanced"}); + defaults_.setValue("max_decomp_weight", 600, "maximal m/z difference used to calculate the decompositions", {"advanced"}); + defaults_.setValue("max_isotope", 3, "max isotope used in the theoretical spectra to score", {"advanced"}); + defaults_.setValue("max_mz", 2000.0, "maximal m/z value used to calculate isotope distributions", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/ANALYSIS/ID/AScore.cpp b/src/openms/source/ANALYSIS/ID/AScore.cpp index ee6a9be24e4..13f9d564cde 100644 --- a/src/openms/source/ANALYSIS/ID/AScore.cpp +++ b/src/openms/source/ANALYSIS/ID/AScore.cpp @@ -52,9 +52,9 @@ namespace OpenMS defaults_.setMinFloat("fragment_mass_tolerance", 0.0); defaults_.setValue("fragment_mass_unit", "Da", "Unit of fragment mass tolerance"); - defaults_.setValidStrings("fragment_mass_unit", ListUtils::create("Da,ppm")); + defaults_.setValidStrings("fragment_mass_unit", {"Da","ppm"}); - vector advanced(1, "advanced"); // tag for advanced parameters + vector advanced(1, "advanced"); // tag for advanced parameters defaults_.setValue("max_peptide_length", 40, "Restrict scoring to peptides with a length no greater than this value ('0' for 'no restriction')", advanced); defaults_.setMinInt("max_peptide_length", 0); diff --git a/src/openms/source/ANALYSIS/ID/AccurateMassSearchEngine.cpp b/src/openms/source/ANALYSIS/ID/AccurateMassSearchEngine.cpp index 5988b587f89..ce23cff9769 100644 --- a/src/openms/source/ANALYSIS/ID/AccurateMassSearchEngine.cpp +++ b/src/openms/source/ANALYSIS/ID/AccurateMassSearchEngine.cpp @@ -536,10 +536,10 @@ namespace OpenMS defaults_.setValue("isotopic_similarity", "false", "Computes a similarity score for each hit (only if the feature exhibits at least two isotopic mass traces)."); defaults_.setValidStrings("isotopic_similarity", {"false", "true"}); - defaults_.setValue("db:mapping", ListUtils::create("CHEMISTRY/HMDBMappingFile.tsv"), "Database input file(s), containing three tab-separated columns of mass, formula, identifier. " + defaults_.setValue("db:mapping", std::vector{"CHEMISTRY/HMDBMappingFile.tsv"}, "Database input file(s), containing three tab-separated columns of mass, formula, identifier. " "If 'mass' is 0, it is re-computed from the molecular sum formula. " "By default CHEMISTRY/HMDBMappingFile.tsv in OpenMS/share is used! If empty, the default will be used."); - defaults_.setValue("db:struct", ListUtils::create("CHEMISTRY/HMDB2StructMapping.tsv"), "Database input file(s), containing four tab-separated columns of identifier, name, SMILES, INCHI." + defaults_.setValue("db:struct", std::vector{"CHEMISTRY/HMDB2StructMapping.tsv"}, "Database input file(s), containing four tab-separated columns of identifier, name, SMILES, INCHI." "The identifier should match with mapping file. SMILES and INCHI are reported in the output, but not used otherwise. " "By default CHEMISTRY/HMDB2StructMapping.tsv in OpenMS/share is used! If empty, the default will be used."); defaults_.setValue("positive_adducts", "CHEMISTRY/PositiveAdducts.tsv", "This file contains the list of potential positive adducts that will be looked for in the database. " @@ -1271,19 +1271,19 @@ namespace OpenMS void AccurateMassSearchEngine::updateMembers_() { mass_error_value_ = (double)param_.getValue("mass_error_value"); - mass_error_unit_ = (String)param_.getValue("mass_error_unit"); - ion_mode_ = (String)param_.getValue("ionization_mode"); + mass_error_unit_ = param_.getValue("mass_error_unit").toString(); + ion_mode_ = param_.getValue("ionization_mode").toString(); iso_similarity_ = param_.getValue("isotopic_similarity").toBool(); // use defaults if empty for all .tsv files - db_mapping_file_ = param_.getValue("db:mapping").toStringList(); - if (db_mapping_file_.empty()) db_mapping_file_ = defaults_.getValue("db:mapping").toStringList(); - db_struct_file_ = param_.getValue("db:struct").toStringList(); - if (db_struct_file_.empty()) db_struct_file_ = defaults_.getValue("db:struct").toStringList(); + db_mapping_file_ = ListUtils::toStringList(param_.getValue("db:mapping")); + if (db_mapping_file_.empty()) db_mapping_file_ = ListUtils::toStringList(defaults_.getValue("db:mapping")); + db_struct_file_ = ListUtils::toStringList(param_.getValue("db:struct")); + if (db_struct_file_.empty()) db_struct_file_ = ListUtils::toStringList(defaults_.getValue("db:struct")); - pos_adducts_fname_ = (String)param_.getValue("positive_adducts"); - neg_adducts_fname_ = (String)param_.getValue("negative_adducts"); + pos_adducts_fname_ = param_.getValue("positive_adducts").toString(); + neg_adducts_fname_ = param_.getValue("negative_adducts").toString(); keep_unidentified_masses_ = param_.getValue("keep_unidentified_masses").toBool(); // database names might have changed, so parse files again before next query diff --git a/src/openms/source/ANALYSIS/ID/BasicProteinInferenceAlgorithm.cpp b/src/openms/source/ANALYSIS/ID/BasicProteinInferenceAlgorithm.cpp index 63c55a8bf9a..a28d65c154c 100644 --- a/src/openms/source/ANALYSIS/ID/BasicProteinInferenceAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/ID/BasicProteinInferenceAlgorithm.cpp @@ -59,7 +59,7 @@ namespace OpenMS defaults_.setValue("score_aggregation_method", "maximum", "How to aggregate scores of peptides matching to the same protein?"); - defaults_.setValidStrings("score_aggregation_method", ListUtils::create("maximum,product,sum")); + defaults_.setValidStrings("score_aggregation_method", {"maximum","product","sum"}); //TODO set valid strings defaults_.setValue("treat_charge_variants_separately", "true", "If this is set, different charge variants of the same peptide sequence count as individual evidences."); diff --git a/src/openms/source/ANALYSIS/ID/BayesianProteinInferenceAlgorithm.cpp b/src/openms/source/ANALYSIS/ID/BayesianProteinInferenceAlgorithm.cpp index bc3da337fbb..ee7845ab30d 100644 --- a/src/openms/source/ANALYSIS/ID/BayesianProteinInferenceAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/ID/BayesianProteinInferenceAlgorithm.cpp @@ -203,7 +203,7 @@ namespace OpenMS .getValue("loopy_belief_propagation:dampening_lambda"); double initConvergenceThreshold = param_.getValue( "loopy_belief_propagation:convergence_threshold"); - String scheduler_type = param_.getValue( + std::string scheduler_type = param_.getValue( "loopy_belief_propagation:scheduling_type"); std::unique_ptr> scheduler; @@ -309,10 +309,10 @@ namespace OpenMS if (debug_lvl_ > 2) { std::ofstream ofs; - ofs.open ("failed_cc_a"+ String(param_.getValue("model_parameters:pep_emission")) + - "_b" + String(param_.getValue("model_parameters:pep_spurious_emission")) + "_g" + - String(param_.getValue("model_parameters:prot_prior")) + "_c" + - String(param_.getValue("model_parameters:pep_prior")) + "_p" + String(pnorm) + "_" + ofs.open ("failed_cc_a"+ (std::string)param_.getValue("model_parameters:pep_emission") + + "_b" + (std::string)param_.getValue("model_parameters:pep_spurious_emission") + "_g" + + (std::string)param_.getValue("model_parameters:prot_prior") + "_c" + + (std::string)param_.getValue("model_parameters:pep_prior") + "_p" + String(pnorm) + "_" + String(idx) + ".dot" , std::ofstream::out); IDBoostGraph::printGraph(ofs, fg); diff --git a/src/openms/source/ANALYSIS/ID/ConsensusIDAlgorithm.cpp b/src/openms/source/ANALYSIS/ID/ConsensusIDAlgorithm.cpp index 4ac00cb2b35..7a009df9e7a 100644 --- a/src/openms/source/ANALYSIS/ID/ConsensusIDAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/ID/ConsensusIDAlgorithm.cpp @@ -54,10 +54,10 @@ namespace OpenMS defaults_.setMinFloat("filter:min_support", 0.0); defaults_.setMaxFloat("filter:min_support", 1.0); defaults_.setValue("filter:count_empty", "false", "Count empty ID runs (i.e. those containing no peptide hit for the current spectrum) when calculating 'min_support'?"); - defaults_.setValidStrings("filter:count_empty", ListUtils::create("true,false")); + defaults_.setValidStrings("filter:count_empty", {"true","false"}); defaults_.setValue("filter:keep_old_scores", "false", "if set, keeps the original scores as user params"); - defaults_.setValidStrings("filter:keep_old_scores", ListUtils::create("true,false")); + defaults_.setValidStrings("filter:keep_old_scores", {"true","false"}); defaultsToParam_(); } diff --git a/src/openms/source/ANALYSIS/ID/ConsensusIDAlgorithmPEPMatrix.cpp b/src/openms/source/ANALYSIS/ID/ConsensusIDAlgorithmPEPMatrix.cpp index db9309f303b..00eab98aee7 100644 --- a/src/openms/source/ANALYSIS/ID/ConsensusIDAlgorithmPEPMatrix.cpp +++ b/src/openms/source/ANALYSIS/ID/ConsensusIDAlgorithmPEPMatrix.cpp @@ -43,7 +43,7 @@ namespace OpenMS setName("ConsensusIDAlgorithmPEPMatrix"); // DefaultParamHandler defaults_.setValue("matrix", "identity", "Substitution matrix to use for alignment-based similarity scoring"); - defaults_.setValidStrings("matrix", ListUtils::create("identity,PAM30MS")); + defaults_.setValidStrings("matrix", {"identity","PAM30MS"}); defaults_.setValue("penalty", 5, "Alignment gap penalty (the same value is used for gap opening and extension)"); defaults_.setMinInt("penalty", 1); @@ -58,7 +58,7 @@ namespace OpenMS ConsensusIDAlgorithmSimilarity::updateMembers_(); // alignment scoring using SeqAn/similarity matrices: - String matrix = param_.getValue("matrix"); + std::string matrix = param_.getValue("matrix"); int penalty = param_.getValue("penalty"); scoring_method_ = SeqAnScore(-penalty, -penalty); if (matrix == "identity") diff --git a/src/openms/source/ANALYSIS/ID/ConsensusMapMergerAlgorithm.cpp b/src/openms/source/ANALYSIS/ID/ConsensusMapMergerAlgorithm.cpp index 30c5405e37d..386804adfbc 100644 --- a/src/openms/source/ANALYSIS/ID/ConsensusMapMergerAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/ID/ConsensusMapMergerAlgorithm.cpp @@ -45,7 +45,7 @@ namespace OpenMS defaults_.setValue("annotate_origin", "true", "If true, adds a map_index MetaValue to the PeptideIDs to annotate the IDRun they came from."); - defaults_.setValidStrings("annotate_origin", ListUtils::create("true,false")); + defaults_.setValidStrings("annotate_origin", {"true","false"}); defaultsToParam_(); } diff --git a/src/openms/source/ANALYSIS/ID/FIAMSDataProcessor.cpp b/src/openms/source/ANALYSIS/ID/FIAMSDataProcessor.cpp index d638eec7130..1a1543dcd18 100644 --- a/src/openms/source/ANALYSIS/ID/FIAMSDataProcessor.cpp +++ b/src/openms/source/ANALYSIS/ID/FIAMSDataProcessor.cpp @@ -59,18 +59,18 @@ namespace OpenMS { defaults_.setValue("bin_step", 20, "The size of the step to recalculated the bin size used for adding up spectra along the time axis"); - defaults_.setValue("db:mapping", ListUtils::create("CHEMISTRY/HMDBMappingFile.tsv"), "For the accurate mass search. Database input file(s), containing three tab-separated columns of mass, formula, identifier. " + defaults_.setValue("db:mapping", std::vector{"CHEMISTRY/HMDBMappingFile.tsv"}, "For the accurate mass search. Database input file(s), containing three tab-separated columns of mass, formula, identifier. " "If 'mass' is 0, it is re-computed from the molecular sum formula. " "By default CHEMISTRY/HMDBMappingFile.tsv in OpenMS/share is used! If empty, the default will be used."); - defaults_.setValue("db:struct", ListUtils::create("CHEMISTRY/HMDB2StructMapping.tsv"), "For the accurate mass search. Database input file(s), containing four tab-separated columns of identifier, name, SMILES, INCHI." + defaults_.setValue("db:struct", std::vector{"CHEMISTRY/HMDB2StructMapping.tsv"}, "For the accurate mass search. Database input file(s), containing four tab-separated columns of identifier, name, SMILES, INCHI." "The identifier should match with mapping file. SMILES and INCHI are reported in the output, but not used otherwise. " "By default CHEMISTRY/HMDB2StructMapping.tsv in OpenMS/share is used! If empty, the default will be used."); defaults_.setValue("positive_adducts", "CHEMISTRY/PositiveAdducts.tsv", "For the accurate mass search. This file contains the list of potential positive adducts that will be looked for in the database. " "Edit the list if you wish to exclude/include adducts. " - "By default CHEMISTRY/PositiveAdducts.tsv in OpenMS/share is used! If empty, the default will be used.", ListUtils::create("advanced")); + "By default CHEMISTRY/PositiveAdducts.tsv in OpenMS/share is used! If empty, the default will be used.", {"advanced"}); defaults_.setValue("negative_adducts", "CHEMISTRY/NegativeAdducts.tsv", "For the accurate mass search. This file contains the list of potential negative adducts that will be looked for in the database. " "Edit the list if you wish to exclude/include adducts. " - "By default CHEMISTRY/NegativeAdducts.tsv in OpenMS/share is used! If empty, the default will be used.", ListUtils::create("advanced")); + "By default CHEMISTRY/NegativeAdducts.tsv in OpenMS/share is used! If empty, the default will be used.", {"advanced"}); defaults_.setValue("store_progress", "true", "If the intermediate files should be stored in the output directory"); @@ -134,7 +134,7 @@ namespace OpenMS { } FeatureMap FIAMSDataProcessor::convertToFeatureMap(const MSSpectrum& input) { - String polarity_ = param_.getValue("polarity"); + String polarity_ = param_.getValue("polarity").toString(); FeatureMap output; for (auto it = input.begin(); it != input.end(); ++it) { Feature f; @@ -190,8 +190,8 @@ namespace OpenMS { bool FIAMSDataProcessor::run(const MSExperiment& experiment, const float n_seconds, OpenMS::MzTab& output, const bool load_cached_spectrum) { String postfix = String(static_cast(n_seconds)); - String dir_output_ = param_.getValue("dir_output"); - String filename_ = param_.getValue("filename"); + std::string dir_output_ = param_.getValue("dir_output"); + std::string filename_ = param_.getValue("filename"); String filepath_picked = dir_output_ + "/" + filename_ + "_picked_" + postfix + ".mzML"; MSSpectrum picked_spectrum; bool is_cached; diff --git a/src/openms/source/ANALYSIS/ID/FIAMSScheduler.cpp b/src/openms/source/ANALYSIS/ID/FIAMSScheduler.cpp index 412e15adef7..be535793a4d 100644 --- a/src/openms/source/ANALYSIS/ID/FIAMSScheduler.cpp +++ b/src/openms/source/ANALYSIS/ID/FIAMSScheduler.cpp @@ -83,8 +83,8 @@ namespace OpenMS { p.setValue("dir_output", base_dir_ + samples_[i].at("dir_output")); p.setValue("resolution", std::stof(samples_[i].at("resolution"))); p.setValue("polarity", samples_[i].at("charge")); - p.setValue("db:mapping", ListUtils::create(base_dir_ + samples_[i].at("db_mapping"))); - p.setValue("db:struct", ListUtils::create(base_dir_ + samples_[i].at("db_struct"))); + p.setValue("db:mapping", std::vector{base_dir_ + samples_[i].at("db_mapping")}); + p.setValue("db:struct", std::vector{base_dir_ + samples_[i].at("db_struct")}); p.setValue("positive_adducts", base_dir_ + samples_[i].at("positive_adducts")); p.setValue("negative_adducts", base_dir_ + samples_[i].at("negative_adducts")); fia_processor.setParameters(p); diff --git a/src/openms/source/ANALYSIS/ID/FalseDiscoveryRate.cpp b/src/openms/source/ANALYSIS/ID/FalseDiscoveryRate.cpp index ed9b4059720..a9b1e7eaaa5 100644 --- a/src/openms/source/ANALYSIS/ID/FalseDiscoveryRate.cpp +++ b/src/openms/source/ANALYSIS/ID/FalseDiscoveryRate.cpp @@ -50,19 +50,19 @@ namespace OpenMS DefaultParamHandler("FalseDiscoveryRate") { defaults_.setValue("no_qvalues", "false", "If 'true' strict FDRs will be calculated instead of q-values (the default)"); - defaults_.setValidStrings("no_qvalues", ListUtils::create("true,false")); + defaults_.setValidStrings("no_qvalues", {"true","false"}); defaults_.setValue("use_all_hits", "false", "If 'true' not only the first hit, but all are used (peptides only)"); - defaults_.setValidStrings("use_all_hits", ListUtils::create("true,false")); + defaults_.setValidStrings("use_all_hits", {"true","false"}); defaults_.setValue("split_charge_variants", "false", "If 'true' charge variants are treated separately (for peptides of combined target/decoy searches only)."); - defaults_.setValidStrings("split_charge_variants", ListUtils::create("true,false")); + defaults_.setValidStrings("split_charge_variants", {"true","false"}); defaults_.setValue("treat_runs_separately", "false", "If 'true' different search runs are treated separately (for peptides of combined target/decoy searches only)."); - defaults_.setValidStrings("treat_runs_separately", ListUtils::create("true,false")); + defaults_.setValidStrings("treat_runs_separately", {"true","false"}); defaults_.setValue("add_decoy_peptides", "false", "If 'true' decoy peptides will be written to output file, too. The q-value is set to the closest target score."); - defaults_.setValidStrings("add_decoy_peptides", ListUtils::create("true,false")); + defaults_.setValidStrings("add_decoy_peptides", {"true","false"}); defaults_.setValue("add_decoy_proteins", "false", "If 'true' decoy proteins will be written to output file, too. The q-value is set to the closest target score."); - defaults_.setValidStrings("add_decoy_proteins", ListUtils::create("true,false")); + defaults_.setValidStrings("add_decoy_proteins", {"true","false"}); defaults_.setValue("conservative", "true", "If 'true' (D+1)/T instead of (D+1)/(T+D) is used as a formula."); - defaults_.setValidStrings("conservative", ListUtils::create("true,false")); + defaults_.setValidStrings("conservative", {"true","false"}); //defaults_.setValue("equality_epsilon", 0, "The epsilon under which two scores are considered equal."); //defaults_.setMinFloat("equality_epsilon", 0.0); defaultsToParam_(); diff --git a/src/openms/source/ANALYSIS/ID/IDDecoyProbability.cpp b/src/openms/source/ANALYSIS/ID/IDDecoyProbability.cpp index 4c89b4e4159..4c485fed18e 100644 --- a/src/openms/source/ANALYSIS/ID/IDDecoyProbability.cpp +++ b/src/openms/source/ANALYSIS/ID/IDDecoyProbability.cpp @@ -47,12 +47,12 @@ namespace OpenMS IDDecoyProbability::IDDecoyProbability() : DefaultParamHandler("IDDecoyProbability") { - defaults_.setValue("number_of_bins", 40, "Number of bins used for the fitting, if sparse datasets are used, this number should be smaller", ListUtils::create("advanced")); - defaults_.setValue("lower_score_better_default_value_if_zero", 50.0, "This value is used if e.g. a E-value score is 0 and cannot be transformed in a real number (log of E-value)", ListUtils::create("advanced")); + defaults_.setValue("number_of_bins", 40, "Number of bins used for the fitting, if sparse datasets are used, this number should be smaller", {"advanced"}); + defaults_.setValue("lower_score_better_default_value_if_zero", 50.0, "This value is used if e.g. a E-value score is 0 and cannot be transformed in a real number (log of E-value)", {"advanced"}); #ifdef IDDECOYPROBABILITY_DEBUG - defaults_.setValue("rev_filename", "", "bla", ListUtils::create("advanced")); - defaults_.setValue("fwd_filename", "", "bla", ListUtils::create("advanced")); + defaults_.setValue("rev_filename", "", "bla", {"advanced"}); + defaults_.setValue("fwd_filename", "", "bla", {"advanced"}); #endif defaultsToParam_(); diff --git a/src/openms/source/ANALYSIS/ID/IDMapper.cpp b/src/openms/source/ANALYSIS/ID/IDMapper.cpp index 467a93fe5cc..d21ac5637ad 100644 --- a/src/openms/source/ANALYSIS/ID/IDMapper.cpp +++ b/src/openms/source/ANALYSIS/ID/IDMapper.cpp @@ -56,12 +56,12 @@ namespace OpenMS defaults_.setValue("mz_tolerance", mz_tolerance_, "m/z tolerance (in ppm or Da) for the matching"); defaults_.setMinFloat("mz_tolerance", 0); defaults_.setValue("mz_measure", "ppm", "unit of 'mz_tolerance' (ppm or Da)"); - defaults_.setValidStrings("mz_measure", ListUtils::create("ppm,Da")); + defaults_.setValidStrings("mz_measure", {"ppm","Da"}); defaults_.setValue("mz_reference", "precursor", "source of m/z values for peptide identifications"); - defaults_.setValidStrings("mz_reference", ListUtils::create("precursor,peptide")); + defaults_.setValidStrings("mz_reference", {"precursor","peptide"}); defaults_.setValue("ignore_charge", "false", "For feature/consensus maps: Assign an ID independently of whether its charge state matches that of the (consensus) feature."); - defaults_.setValidStrings("ignore_charge", ListUtils::create("true,false")); + defaults_.setValidStrings("ignore_charge", {"true","false"}); defaultsToParam_(); } diff --git a/src/openms/source/ANALYSIS/ID/IDMergerAlgorithm.cpp b/src/openms/source/ANALYSIS/ID/IDMergerAlgorithm.cpp index a4a76bfe2f8..6e23f1e29cf 100644 --- a/src/openms/source/ANALYSIS/ID/IDMergerAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/ID/IDMergerAlgorithm.cpp @@ -54,11 +54,11 @@ namespace OpenMS defaults_.setValue("annotate_origin", "true", "If true, adds a map_index MetaValue to the PeptideIDs to annotate the IDRun they came from."); - defaults_.setValidStrings("annotate_origin", ListUtils::create("true,false")); + defaults_.setValidStrings("annotate_origin", {"true","false"}); defaults_.setValue("allow_disagreeing_settings", "false", "Force merging of disagreeing runs. Use at your own risk."); - defaults_.setValidStrings("allow_disagreeing_settings", ListUtils::create("true,false")); + defaults_.setValidStrings("allow_disagreeing_settings", {"true","false"}); defaultsToParam_(); prot_result_.setIdentifier(getNewIdentifier_()); } diff --git a/src/openms/source/ANALYSIS/ID/IDScoreSwitcherAlgorithm.cpp b/src/openms/source/ANALYSIS/ID/IDScoreSwitcherAlgorithm.cpp index 98aefacf04e..f97ea912509 100644 --- a/src/openms/source/ANALYSIS/ID/IDScoreSwitcherAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/ID/IDScoreSwitcherAlgorithm.cpp @@ -56,9 +56,9 @@ namespace OpenMS void IDScoreSwitcherAlgorithm::updateMembers_() { - new_score_ = param_.getValue("new_score"); - new_score_type_ = param_.getValue("new_score_type"); - old_score_ = param_.getValue("old_score"); + new_score_ = param_.getValue("new_score").toString(); + new_score_type_ = param_.getValue("new_score_type").toString(); + old_score_ = param_.getValue("old_score").toString(); higher_better_ = (param_.getValue("new_score_orientation").toString() == "higher_better"); diff --git a/src/openms/source/ANALYSIS/ID/MetaboliteSpectralMatching.cpp b/src/openms/source/ANALYSIS/ID/MetaboliteSpectralMatching.cpp index 4be68877096..6b2e6dc20e6 100644 --- a/src/openms/source/ANALYSIS/ID/MetaboliteSpectralMatching.cpp +++ b/src/openms/source/ANALYSIS/ID/MetaboliteSpectralMatching.cpp @@ -289,13 +289,13 @@ namespace OpenMS defaults_.setValue("frag_mass_error_value", 500.0, "Error allowed for product ions."); defaults_.setValue("mass_error_unit", "ppm", "Unit of mass error (ppm or Da)"); - defaults_.setValidStrings("mass_error_unit", ListUtils::create(("ppm,Da"))); + defaults_.setValidStrings("mass_error_unit", {"ppm","Da"}); defaults_.setValue("report_mode", "top3", "Which results shall be reported: the top-three scoring ones or the best scoring one?"); - defaults_.setValidStrings("report_mode", ListUtils::create(("top3,best"))); + defaults_.setValidStrings("report_mode", {"top3","best"}); defaults_.setValue("ionization_mode", "positive", "Positive or negative ionization mode?"); - defaults_.setValidStrings("ionization_mode", ListUtils::create(("positive,negative"))); + defaults_.setValidStrings("ionization_mode", {"positive","negative"}); defaultsToParam_(); @@ -591,10 +591,10 @@ namespace OpenMS { precursor_mz_error_ = (double)param_.getValue("prec_mass_error_value"); fragment_mz_error_ = (double)param_.getValue("frag_mass_error_value"); - ion_mode_ = (String)param_.getValue("ionization_mode"); + ion_mode_ = param_.getValue("ionization_mode").toString(); - mz_error_unit_ = (String)param_.getValue("mass_error_unit"); - report_mode_ = (String)param_.getValue("report_mode"); + mz_error_unit_ = param_.getValue("mass_error_unit").toString(); + report_mode_ = param_.getValue("report_mode").toString(); } diff --git a/src/openms/source/ANALYSIS/ID/PeptideIndexing.cpp b/src/openms/source/ANALYSIS/ID/PeptideIndexing.cpp index e47666db39d..b548d7f14cb 100644 --- a/src/openms/source/ANALYSIS/ID/PeptideIndexing.cpp +++ b/src/openms/source/ANALYSIS/ID/PeptideIndexing.cpp @@ -53,14 +53,15 @@ using namespace std; defaults_.setValidStrings("decoy_string_position", { "prefix", "suffix" }); defaults_.setValue("missing_decoy_action", names_of_missing_decoy[(Size)MissingDecoy::IS_ERROR], "Action to take if NO peptide was assigned to a decoy protein (which indicates wrong database or decoy string): 'error' (exit with error, no output), 'warn' (exit with success, warning message), 'silent' (no action is taken, not even a warning)"); - defaults_.setValidStrings("missing_decoy_action", StringList(names_of_missing_decoy.begin(), names_of_missing_decoy.end())); + defaults_.setValidStrings("missing_decoy_action", std::vector(names_of_missing_decoy.begin(), names_of_missing_decoy.end())); defaults_.setValue("enzyme:name", AUTO_MODE, "Enzyme which determines valid cleavage sites - e.g. trypsin cleaves after lysine (K) or arginine (R), but not before proline (P). Default: deduce from input"); StringList enzymes{}; ProteaseDB::getInstance()->getAllNames(enzymes); enzymes.emplace(enzymes.begin(), AUTO_MODE); // make it the first item - defaults_.setValidStrings("enzyme:name", enzymes); + + defaults_.setValidStrings("enzyme:name", ListUtils::create(enzymes)); defaults_.setValue("enzyme:specificity", AUTO_MODE, "Specificity of the enzyme. Default: deduce from input." "\n '" + EnzymaticDigestion::NamesOfSpecificity[EnzymaticDigestion::SPEC_FULL] + "': both internal cleavage sites must match." @@ -82,7 +83,7 @@ using namespace std; defaults_.setValidStrings("keep_unreferenced_proteins", { "true", "false" }); defaults_.setValue("unmatched_action", names_of_unmatched[(Size)Unmatched::IS_ERROR], "If peptide sequences cannot be matched to any protein: 1) raise an error; 2) warn (unmatched PepHits will miss target/decoy annotation with downstream problems); 3) remove the hit."); - defaults_.setValidStrings("unmatched_action", StringList(names_of_unmatched.begin(), names_of_unmatched.end())); + defaults_.setValidStrings("unmatched_action", std::vector(names_of_unmatched.begin(), names_of_unmatched.end())); defaults_.setValue("aaa_max", 3, "Maximal number of ambiguous amino acids (AAAs) allowed when matching to a protein database with AAAs. AAAs are B, J, Z and X!"); defaults_.setMinInt("aaa_max", 0); @@ -105,11 +106,11 @@ using namespace std; void PeptideIndexing::updateMembers_() { - decoy_string_ = static_cast(param_.getValue("decoy_string")); + decoy_string_ = param_.getValue("decoy_string").toString(); prefix_ = (param_.getValue("decoy_string_position") == "prefix" ? true : false); missing_decoy_action_ = (MissingDecoy)Helpers::indexOf(names_of_missing_decoy, param_.getValue("missing_decoy_action")); - enzyme_name_ = static_cast(param_.getValue("enzyme:name")); - enzyme_specificity_ = static_cast(param_.getValue("enzyme:specificity")); + enzyme_name_ = param_.getValue("enzyme:name").toString(); + enzyme_specificity_ = param_.getValue("enzyme:specificity").toString(); write_protein_sequence_ = param_.getValue("write_protein_sequence").toBool(); write_protein_description_ = param_.getValue("write_protein_description").toBool(); diff --git a/src/openms/source/ANALYSIS/ID/ProtonDistributionModel.cpp b/src/openms/source/ANALYSIS/ID/ProtonDistributionModel.cpp index 3db0dc3e26e..a5f248384bd 100644 --- a/src/openms/source/ANALYSIS/ID/ProtonDistributionModel.cpp +++ b/src/openms/source/ANALYSIS/ID/ProtonDistributionModel.cpp @@ -59,12 +59,12 @@ namespace OpenMS E_c_term_(0), E_n_term_(0) { - defaults_.setValue("gb_bb_l_NH2", 916.84, "Gas-phase basicity value of N-terminus", ListUtils::create("advanced")); - defaults_.setValue("gb_bb_r_COOH", -95.82, "Gas-phase basicity value of C-terminus", ListUtils::create("advanced")); - defaults_.setValue("gb_bb_r_b-ion", 36.46, "Gas-phase basicity value of b-ion C-terminus", ListUtils::create("advanced")); - defaults_.setValue("gb_bb_r_a-ion", 46.85, "Gas-phase basicity value of a-ion C-terminus", ListUtils::create("advanced")); - defaults_.setValue("sigma", 0.5, "Width of the gaussian which distributes the mobile protons over the charge states, only for z > 3.", ListUtils::create("advanced")); - defaults_.setValue("temperature", 500.0, "Temperature term ", ListUtils::create("advanced")); + defaults_.setValue("gb_bb_l_NH2", 916.84, "Gas-phase basicity value of N-terminus", {"advanced"}); + defaults_.setValue("gb_bb_r_COOH", -95.82, "Gas-phase basicity value of C-terminus", {"advanced"}); + defaults_.setValue("gb_bb_r_b-ion", 36.46, "Gas-phase basicity value of b-ion C-terminus", {"advanced"}); + defaults_.setValue("gb_bb_r_a-ion", 46.85, "Gas-phase basicity value of a-ion C-terminus", {"advanced"}); + defaults_.setValue("sigma", 0.5, "Width of the gaussian which distributes the mobile protons over the charge states, only for z > 3.", {"advanced"}); + defaults_.setValue("temperature", 500.0, "Temperature term ", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/ANALYSIS/ID/SimpleSearchEngineAlgorithm.cpp b/src/openms/source/ANALYSIS/ID/SimpleSearchEngineAlgorithm.cpp index 6668e05440d..badb8d59d75 100644 --- a/src/openms/source/ANALYSIS/ID/SimpleSearchEngineAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/ID/SimpleSearchEngineAlgorithm.cpp @@ -89,7 +89,7 @@ namespace OpenMS { defaults_.setValue("precursor:mass_tolerance", 10.0, "Width of precursor mass tolerance window"); - StringList precursor_mass_tolerance_unit_valid_strings; + std::vector precursor_mass_tolerance_unit_valid_strings; precursor_mass_tolerance_unit_valid_strings.push_back("ppm"); precursor_mass_tolerance_unit_valid_strings.push_back("Da"); @@ -107,7 +107,7 @@ namespace OpenMS defaults_.setValue("fragment:mass_tolerance", 10.0, "Fragment mass tolerance"); - StringList fragment_mass_tolerance_unit_valid_strings; + std::vector fragment_mass_tolerance_unit_valid_strings; fragment_mass_tolerance_unit_valid_strings.push_back("ppm"); fragment_mass_tolerance_unit_valid_strings.push_back("Da"); @@ -118,23 +118,25 @@ namespace OpenMS vector all_mods; ModificationsDB::getInstance()->getAllSearchModifications(all_mods); - defaults_.setValue("modifications:fixed", ListUtils::create("Carbamidomethyl (C)", ','), "Fixed modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)'"); - defaults_.setValidStrings("modifications:fixed", all_mods); - defaults_.setValue("modifications:variable", ListUtils::create("Oxidation (M)", ','), "Variable modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Oxidation (M)'"); - defaults_.setValidStrings("modifications:variable", all_mods); + + defaults_.setValue("modifications:fixed", std::vector{"Carbamidomethyl (C)"}, "Fixed modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)'"); + defaults_.setValidStrings("modifications:fixed", ListUtils::create(all_mods)); + defaults_.setValue("modifications:variable", std::vector{"Oxidation (M)"}, "Variable modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Oxidation (M)'"); + defaults_.setValidStrings("modifications:variable", ListUtils::create(all_mods)); defaults_.setValue("modifications:variable_max_per_peptide", 2, "Maximum number of residues carrying a variable modification per candidate peptide"); defaults_.setSectionDescription("modifications", "Modifications Options"); vector all_enzymes; ProteaseDB::getInstance()->getAllNames(all_enzymes); + defaults_.setValue("enzyme", "Trypsin", "The enzyme used for peptide digestion."); - defaults_.setValidStrings("enzyme", all_enzymes); + defaults_.setValidStrings("enzyme", ListUtils::create(all_enzymes)); defaults_.setValue("decoys", "false", "Should decoys be generated?"); defaults_.setValidStrings("decoys", {"true","false"} ); - defaults_.setValue("annotate:PSM", StringList{}, "Annotations added to each PSM."); - defaults_.setValidStrings("annotate:PSM", StringList{Constants::UserParam::FRAGMENT_ERROR_MEDIAN_PPM_USERPARAM, Constants::UserParam::PRECURSOR_ERROR_PPM_USERPARAM}); + defaults_.setValue("annotate:PSM", std::vector{}, "Annotations added to each PSM."); + defaults_.setValidStrings("annotate:PSM", std::vector{Constants::UserParam::FRAGMENT_ERROR_MEDIAN_PPM_USERPARAM, Constants::UserParam::PRECURSOR_ERROR_PPM_USERPARAM}); defaults_.setSectionDescription("annotate", "Annotation Options"); defaults_.setValue("peptide:min_size", 7, "Minimum size a peptide must have after digestion to be considered in the search."); @@ -152,7 +154,7 @@ namespace OpenMS void SimpleSearchEngineAlgorithm::updateMembers_() { precursor_mass_tolerance_ = param_.getValue("precursor:mass_tolerance"); - precursor_mass_tolerance_unit_ = param_.getValue("precursor:mass_tolerance_unit"); + precursor_mass_tolerance_unit_ = param_.getValue("precursor:mass_tolerance_unit").toString(); precursor_min_charge_ = param_.getValue("precursor:min_charge"); precursor_max_charge_ = param_.getValue("precursor:max_charge"); @@ -161,25 +163,25 @@ namespace OpenMS fragment_mass_tolerance_ = param_.getValue("fragment:mass_tolerance"); - fragment_mass_tolerance_unit_ = param_.getValue("fragment:mass_tolerance_unit"); + fragment_mass_tolerance_unit_ = param_.getValue("fragment:mass_tolerance_unit").toString(); - modifications_fixed_ = param_.getValue("modifications:fixed"); + modifications_fixed_ = ListUtils::toStringList(param_.getValue("modifications:fixed")); - modifications_variable_ = param_.getValue("modifications:variable"); + modifications_variable_ = ListUtils::toStringList(param_.getValue("modifications:variable")); modifications_max_variable_mods_per_peptide_ = param_.getValue("modifications:variable_max_per_peptide"); - enzyme_ = param_.getValue("enzyme"); + enzyme_ = param_.getValue("enzyme").toString(); peptide_min_size_ = param_.getValue("peptide:min_size"); peptide_max_size_ = param_.getValue("peptide:max_size"); peptide_missed_cleavages_ = param_.getValue("peptide:missed_cleavages"); - peptide_motif_ = param_.getValue("peptide:motif"); + peptide_motif_ = param_.getValue("peptide:motif").toString(); report_top_hits_ = param_.getValue("report:top_hits"); decoys_ = param_.getValue("decoys") == "true"; - annotate_psm_ = param_.getValue("annotate:PSM"); + annotate_psm_ = ListUtils::toStringList(param_.getValue("annotate:PSM")); } // static @@ -466,10 +468,8 @@ void SimpleSearchEngineAlgorithm::postProcessHits_(const PeakMap& exp, for (size_t i = 0; i != annotated_hits_lock.size(); i++) { omp_init_lock(&(annotated_hits_lock[i])); } #endif - startProgress(0, 1, "Load database from FASTA file..."); vector fasta_db; - FASTAFile::load(in_db, fasta_db); - endProgress(); + FASTAFile().load(in_db, fasta_db); ProteaseDigestion digestor; digestor.setEnzyme(enzyme_); diff --git a/src/openms/source/ANALYSIS/ID/SiriusAdapterAlgorithm.cpp b/src/openms/source/ANALYSIS/ID/SiriusAdapterAlgorithm.cpp index 584fe791408..508ce579059 100644 --- a/src/openms/source/ANALYSIS/ID/SiriusAdapterAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/ID/SiriusAdapterAlgorithm.cpp @@ -56,7 +56,7 @@ namespace OpenMS using FingeridName = String; using PassatuttoName = String; using OpenMSName = String; - using DefaultValue = DataValue; + using DefaultValue = ParamValue; using Description = String; SiriusAdapterAlgorithm::SiriusAdapterAlgorithm() : @@ -316,10 +316,10 @@ namespace OpenMS { for (auto it = param.begin(); it != param.end(); ++it) { - const String name = it.getName(); + const std::string name = it.getName(); if (hasFullNameParameter(name)) { - vector tags(it->tags.begin(), it->tags.end()); + vector tags(it->tags.begin(), it->tags.end()); param_.setValue(name, it->value, it->description, tags); } } @@ -611,7 +611,7 @@ namespace OpenMS SiriusAdapterAlgorithm::ParameterModifier SiriusAdapterAlgorithm::ParameterSection::parameter( const String ¶meter_name, - const DataValue &default_value, + const ParamValue &default_value, const String ¶meter_description) { const String full_parameter = toFullParameter(parameter_name); diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/FeatureDistance.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/FeatureDistance.cpp index 6e7ff68aa30..be4aba94f3e 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/FeatureDistance.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/FeatureDistance.cpp @@ -57,33 +57,33 @@ namespace OpenMS { defaults_.setValue("distance_RT:max_difference", 100.0, "Never pair features with a larger RT distance (in seconds)."); defaults_.setMinFloat("distance_RT:max_difference", 0.0); - defaults_.setValue("distance_RT:exponent", 1.0, "Normalized RT differences ([0-1], relative to 'max_difference') are raised to this power (using 1 or 2 will be fast, everything else is REALLY slow)", ListUtils::create("advanced")); + defaults_.setValue("distance_RT:exponent", 1.0, "Normalized RT differences ([0-1], relative to 'max_difference') are raised to this power (using 1 or 2 will be fast, everything else is REALLY slow)", {"advanced"}); defaults_.setMinFloat("distance_RT:exponent", 0.0); - defaults_.setValue("distance_RT:weight", 1.0, "Final RT distances are weighted by this factor", ListUtils::create("advanced")); + defaults_.setValue("distance_RT:weight", 1.0, "Final RT distances are weighted by this factor", {"advanced"}); defaults_.setMinFloat("distance_RT:weight", 0.0); defaults_.setSectionDescription("distance_RT", "Distance component based on RT differences"); defaults_.setValue("distance_MZ:max_difference", 0.3, "Never pair features with larger m/z distance (unit defined by 'unit')"); defaults_.setMinFloat("distance_MZ:max_difference", 0.0); defaults_.setValue("distance_MZ:unit", "Da", "Unit of the 'max_difference' parameter"); - defaults_.setValidStrings("distance_MZ:unit", ListUtils::create("Da,ppm")); - defaults_.setValue("distance_MZ:exponent", 2.0, "Normalized ([0-1], relative to 'max_difference') m/z differences are raised to this power (using 1 or 2 will be fast, everything else is REALLY slow)", ListUtils::create("advanced")); + defaults_.setValidStrings("distance_MZ:unit", {"Da","ppm"}); + defaults_.setValue("distance_MZ:exponent", 2.0, "Normalized ([0-1], relative to 'max_difference') m/z differences are raised to this power (using 1 or 2 will be fast, everything else is REALLY slow)", {"advanced"}); defaults_.setMinFloat("distance_MZ:exponent", 0.0); - defaults_.setValue("distance_MZ:weight", 1.0, "Final m/z distances are weighted by this factor", ListUtils::create("advanced")); + defaults_.setValue("distance_MZ:weight", 1.0, "Final m/z distances are weighted by this factor", {"advanced"}); defaults_.setMinFloat("distance_MZ:weight", 0.0); defaults_.setSectionDescription("distance_MZ", "Distance component based on m/z differences"); - defaults_.setValue("distance_intensity:exponent", 1.0, "Differences in relative intensity ([0-1]) are raised to this power (using 1 or 2 will be fast, everything else is REALLY slow)", ListUtils::create("advanced")); + defaults_.setValue("distance_intensity:exponent", 1.0, "Differences in relative intensity ([0-1]) are raised to this power (using 1 or 2 will be fast, everything else is REALLY slow)", {"advanced"}); defaults_.setMinFloat("distance_intensity:exponent", 0.0); - defaults_.setValue("distance_intensity:weight", 0.0, "Final intensity distances are weighted by this factor", ListUtils::create("advanced")); + defaults_.setValue("distance_intensity:weight", 0.0, "Final intensity distances are weighted by this factor", {"advanced"}); defaults_.setMinFloat("distance_intensity:weight", 0.0); - defaults_.setValue("distance_intensity:log_transform", "disabled", "Log-transform intensities? If disabled, d = |int_f2 - int_f1| / int_max. If enabled, d = |log(int_f2 + 1) - log(int_f1 + 1)| / log(int_max + 1))", ListUtils::create("advanced")); - defaults_.setValidStrings("distance_intensity:log_transform", ListUtils::create("enabled,disabled")); + defaults_.setValue("distance_intensity:log_transform", "disabled", "Log-transform intensities? If disabled, d = |int_f2 - int_f1| / int_max. If enabled, d = |log(int_f2 + 1) - log(int_f1 + 1)| / log(int_max + 1))", {"advanced"}); + defaults_.setValidStrings("distance_intensity:log_transform", {"enabled","disabled"}); defaults_.setSectionDescription("distance_intensity", "Distance component based on differences in relative intensity (usually relative to highest peak in the whole data set)"); defaults_.setValue("ignore_charge", "false", "false [default]: pairing requires equal charge state (or at least one unknown charge '0'); true: Pairing irrespective of charge state"); - defaults_.setValidStrings("ignore_charge", ListUtils::create("true,false")); + defaults_.setValidStrings("ignore_charge", {"true","false"}); defaults_.setValue("ignore_adduct", "true", "true [default]: pairing requires equal adducts (or at least one without adduct annotation); true: Pairing irrespective of adducts"); - defaults_.setValidStrings("ignore_adduct", ListUtils::create("true,false")); + defaults_.setValidStrings("ignore_adduct", {"true","false"}); defaultsToParam_(); @@ -123,8 +123,8 @@ namespace OpenMS params_intensity_ = DistanceParams_("intensity", param_); total_weight_reciprocal_ = 1 / (params_rt_.weight + params_mz_.weight + params_intensity_.weight); - ignore_charge_ = String(param_.getValue("ignore_charge")) == "true"; - ignore_adduct_ = String(param_.getValue("ignore_adduct")) == "true"; + ignore_charge_ = param_.getValue("ignore_charge").toBool(); + ignore_adduct_ = param_.getValue("ignore_adduct").toBool(); } double FeatureDistance::distance_(double diff, const DistanceParams_ & params) const diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/FeatureGroupingAlgorithmKD.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/FeatureGroupingAlgorithmKD.cpp index 749f3810672..3ceda6f4363 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/FeatureGroupingAlgorithmKD.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/FeatureGroupingAlgorithmKD.cpp @@ -50,16 +50,16 @@ namespace OpenMS setName("FeatureGroupingAlgorithmKD"); defaults_.setValue("warp:enabled", "true", "Whether or not to internally warp feature RTs using LOWESS transformation before linking (reported RTs in results will always be the original RTs)"); - defaults_.setValidStrings("warp:enabled", ListUtils::create("true,false")); + defaults_.setValidStrings("warp:enabled", {"true","false"}); defaults_.setValue("warp:rt_tol", 100.0, "Width of RT tolerance window (sec)"); defaults_.setMinFloat("warp:rt_tol", 0.0); defaults_.setValue("warp:mz_tol", 5.0, "m/z tolerance (in ppm or Da)"); defaults_.setMinFloat("warp:mz_tol", 0.0); - defaults_.setValue("warp:max_pairwise_log_fc", 0.5, "Maximum absolute log10 fold change between two compatible signals during compatibility graph construction. Two signals from different maps will not be connected by an edge in the compatibility graph if absolute log fold change exceeds this limit (they might still end up in the same connected component, however). Note: this does not limit fold changes in the linking stage, only during RT alignment, where we try to find high-quality alignment anchor points. Setting this to a value < 0 disables the FC check.", ListUtils::create("advanced")); - defaults_.setValue("warp:min_rel_cc_size", 0.5, "Only connected components containing compatible features from at least max(2, (warp_min_occur * number_of_input_maps)) input maps are considered for computing the warping function", ListUtils::create("advanced")); + defaults_.setValue("warp:max_pairwise_log_fc", 0.5, "Maximum absolute log10 fold change between two compatible signals during compatibility graph construction. Two signals from different maps will not be connected by an edge in the compatibility graph if absolute log fold change exceeds this limit (they might still end up in the same connected component, however). Note: this does not limit fold changes in the linking stage, only during RT alignment, where we try to find high-quality alignment anchor points. Setting this to a value < 0 disables the FC check.", {"advanced"}); + defaults_.setValue("warp:min_rel_cc_size", 0.5, "Only connected components containing compatible features from at least max(2, (warp_min_occur * number_of_input_maps)) input maps are considered for computing the warping function", {"advanced"}); defaults_.setMinFloat("warp:min_rel_cc_size", 0.0); defaults_.setMaxFloat("warp:min_rel_cc_size", 1.0); - defaults_.setValue("warp:max_nr_conflicts", 0, "Allow up to this many conflicts (features from the same map) per connected component to be used for alignment (-1 means allow any number of conflicts)", ListUtils::create("advanced")); + defaults_.setValue("warp:max_nr_conflicts", 0, "Allow up to this many conflicts (features from the same map) per connected component to be used for alignment (-1 means allow any number of conflicts)", {"advanced"}); defaults_.setMinInt("warp:max_nr_conflicts", -1); defaults_.setValue("link:rt_tol", 30.0, "Width of RT tolerance window (sec)"); @@ -72,7 +72,7 @@ namespace OpenMS defaults_.setValidStrings("link:adduct_merging", {"Identical", "With_unknown_adducts", "Any"}); defaults_.setValue("mz_unit", "ppm", "Unit of m/z tolerance"); - defaults_.setValidStrings("mz_unit", ListUtils::create("ppm,Da")); + defaults_.setValidStrings("mz_unit", {"ppm","Da"}); defaults_.setValue("nr_partitions", 100, "Number of partitions in m/z space"); defaults_.setMinInt("nr_partitions", 1); diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/LabeledPairFinder.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/LabeledPairFinder.cpp index 602ec9a4fb3..3025006f8d2 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/LabeledPairFinder.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/LabeledPairFinder.cpp @@ -57,7 +57,7 @@ namespace OpenMS "Note that this works only datasets with a significant amount of pairs! " "If 'false' the parameters 'rt_pair_dist', 'rt_dev_low' " "and 'rt_dev_high' define the optimal distance."); - defaults_.setValidStrings("rt_estimate", ListUtils::create("true,false")); + defaults_.setValidStrings("rt_estimate", {"true","false"}); defaults_.setValue("rt_pair_dist", -20.0, "optimal pair distance in RT [sec] from light to heavy feature"); defaults_.setValue("rt_dev_low", 15.0, "maximum allowed deviation below optimal retention time distance"); defaults_.setMinFloat("rt_dev_low", 0.0); @@ -67,8 +67,8 @@ namespace OpenMS defaults_.setValue("mz_pair_dists", ListUtils::create("4.0"), "optimal pair distances in m/z [Th] for features with charge +1 (adapted to +2, +3, .. by division through charge)"); defaults_.setValue("mz_dev", 0.05, "maximum allowed deviation from optimal m/z distance\n"); defaults_.setMinFloat("mz_dev", 0.0); - defaults_.setValue("mrm", "false", "this option should be used if the features correspond mrm chromatograms (additionally the precursor is taken into account)", ListUtils::create("advanced")); - defaults_.setValidStrings("mrm", ListUtils::create("true,false")); + defaults_.setValue("mrm", "false", "this option should be used if the features correspond mrm chromatograms (additionally the precursor is taken into account)", {"advanced"}); + defaults_.setValidStrings("mrm", {"true","false"}); defaultsToParam_(); } diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmIdentification.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmIdentification.cpp index 5128878eae6..ef6684d4594 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmIdentification.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmIdentification.cpp @@ -57,10 +57,10 @@ namespace OpenMS defaults_.setValue("use_unassigned_peptides", "true", "Should unassigned peptide identifications be used when computing an alignment of feature or consensus maps? If 'false', only peptide IDs assigned to features will be used."); defaults_.setValidStrings("use_unassigned_peptides", - ListUtils::create("true,false")); + {"true","false"}); defaults_.setValue("use_feature_rt", "false", "When aligning feature or consensus maps, don't use the retention time of a peptide identification directly; instead, use the retention time of the centroid of the feature (apex of the elution profile) that the peptide was matched to. If different identifications are matched to one feature, only the peptide closest to the centroid in RT is used.\nPrecludes 'use_unassigned_peptides'."); - defaults_.setValidStrings("use_feature_rt", ListUtils::create("true,false")); + defaults_.setValidStrings("use_feature_rt", {"true","false"}); defaultsToParam_(); } diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmSpectrumAlignment.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmSpectrumAlignment.cpp index c81229cf482..e0054c88982 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmSpectrumAlignment.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmSpectrumAlignment.cpp @@ -50,20 +50,20 @@ namespace OpenMS defaults_.setMinFloat("gapcost", 0.0); defaults_.setValue("affinegapcost", 0.5, "This Parameter controls the cost of extension a already open gap. The idea behind the affine gapcost lies under the assumption, that it is better to get a long distance of connected gaps than to have a structure of gaps interspersed with matches (gap match gap match etc.). Therefore the punishment for the extension of a gap generally should be lower than the normal gapcost. If the result of the alignment shows high compression, it is a good idea to lower either the affine gapcost or gap opening cost."); defaults_.setMinFloat("affinegapcost", 0.0); - defaults_.setValue("cutoff_score", 0.70, "The Parameter defines the threshold which filtered spectra, these spectra are high potential candidate for deciding the interval of a sub-alignment. Only those pair of spectra are selected, which has a score higher or same of the threshold.", ListUtils::create("advanced")); + defaults_.setValue("cutoff_score", 0.70, "The Parameter defines the threshold which filtered spectra, these spectra are high potential candidate for deciding the interval of a sub-alignment. Only those pair of spectra are selected, which has a score higher or same of the threshold.", {"advanced"}); defaults_.setMinFloat("cutoff_score", 0.0); defaults_.setMaxFloat("cutoff_score", 1.0); - defaults_.setValue("bucketsize", 100, "Defines the numbers of buckets. It is a quantize of the interval of those points, which defines the main alignment (match points). These points have to filtered, to reduce the amount of points for the calculating a smoother spline curve.", ListUtils::create("advanced")); + defaults_.setValue("bucketsize", 100, "Defines the numbers of buckets. It is a quantize of the interval of those points, which defines the main alignment (match points). These points have to filtered, to reduce the amount of points for the calculating a smoother spline curve.", {"advanced"}); defaults_.setMinInt("bucketsize", 1); - defaults_.setValue("anchorpoints", 100, "Defines the percent of numbers of match points which a selected from one bucket. The high score pairs are previously selected. The reduction of match points helps to get a smoother spline curve.", ListUtils::create("advanced")); - defaults_.setValue("debug", "false", "Activate the debug mode, there a files written starting with debug prefix.", ListUtils::create("advanced")); + defaults_.setValue("anchorpoints", 100, "Defines the percent of numbers of match points which a selected from one bucket. The high score pairs are previously selected. The reduction of match points helps to get a smoother spline curve.", {"advanced"}); + defaults_.setValue("debug", "false", "Activate the debug mode, there a files written starting with debug prefix.", {"advanced"}); defaults_.setMinInt("anchorpoints", 1); defaults_.setMaxInt("anchorpoints", 100); - defaults_.setValidStrings("debug", ListUtils::create("true,false")); - defaults_.setValue("mismatchscore", -5.0, "Defines the score of two spectra if they have no similarity to each other. ", ListUtils::create("advanced")); + defaults_.setValidStrings("debug", {"true","false"}); + defaults_.setValue("mismatchscore", -5.0, "Defines the score of two spectra if they have no similarity to each other. ", {"advanced"}); defaults_.setMaxFloat("mismatchscore", 0.0); defaults_.setValue("scorefunction", "SteinScottImproveScore", "The score function is the core of an alignment. The success of an alignment depends mostly of the elected score function. The score function return the similarity of two spectra. The score influence defines later the way of possible traceback. There are multiple spectra similarity scores available.."); - defaults_.setValidStrings("scorefunction", ListUtils::create("SteinScottImproveScore,ZhangSimilarityScore")); //Factory::registeredProducts()); + defaults_.setValidStrings("scorefunction", {"SteinScottImproveScore","ZhangSimilarityScore"}); //Factory::registeredProducts()); defaultsToParam_(); setLogType(CMD); } @@ -809,9 +809,9 @@ namespace OpenMS e_ = (float)param_.getValue("affinegapcost"); // create spectrum compare functor if it does not yet exist - if (c1_ == nullptr || c1_->getName() != (String)param_.getValue("scorefunction")) + if (c1_ == nullptr || c1_->getName() != param_.getValue("scorefunction")) { - c1_ = Factory::create((String)param_.getValue("scorefunction")); + c1_ = Factory::create(param_.getValue("scorefunction").toString()); } cutoffScore_ = (float)param_.getValue("cutoff_score"); @@ -825,8 +825,7 @@ namespace OpenMS anchorPoints_ = 100; } - String tmp = (String)param_.getValue("debug"); - debug_ = (tmp == "true"); + debug_ = param_.getValue("debug").toBool(); threshold_ = 1 - cutoffScore_; } diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmTreeGuided.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmTreeGuided.cpp index e9b54246cfe..38f294e5e11 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmTreeGuided.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/MapAlignmentAlgorithmTreeGuided.cpp @@ -69,7 +69,7 @@ namespace OpenMS { align_algorithm_.setParameters(param_.copy("align_algorithm:", true)); model_param_ = param_.copy("model:",true); - model_type_ = param_.getValue("model_type"); + model_type_ = param_.getValue("model_type").toString(); model_param_ = model_param_.copy(model_type_+":", true); } diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/PoseClusteringAffineSuperimposer.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/PoseClusteringAffineSuperimposer.cpp index f763ab7023b..18a9d0cb3c1 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/PoseClusteringAffineSuperimposer.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/PoseClusteringAffineSuperimposer.cpp @@ -54,7 +54,7 @@ namespace OpenMS defaults_.setValue("rt_pair_distance_fraction", 0.1, "Within each of the two maps, the pairs considered for pose clustering " "must be separated by at least this fraction of the total elution time " - "interval (i.e., max - min). ", ListUtils::create("advanced")); + "interval (i.e., max - min). ", {"advanced"}); defaults_.setMinFloat("rt_pair_distance_fraction", 0.); defaults_.setMaxFloat("rt_pair_distance_fraction", 1.); @@ -76,18 +76,18 @@ namespace OpenMS defaults_.setMinFloat("shift_bucket_size", 0.); defaults_.setValue("max_shift", 1000.0, "Maximal shift which is considered during histogramming (in seconds). " - "This applies for both directions.", ListUtils::create("advanced")); + "This applies for both directions.", {"advanced"}); defaults_.setMinFloat("max_shift", 0.); defaults_.setValue("max_scaling", 2.0, "Maximal scaling which is considered during histogramming. " - "The minimal scaling is the reciprocal of this.", ListUtils::create("advanced")); + "The minimal scaling is the reciprocal of this.", {"advanced"}); defaults_.setMinFloat("max_scaling", 1.); defaults_.setValue("dump_buckets", "", "[DEBUG] If non-empty, base filename where hash table buckets will be dumped to. " - "A serial number for each invocation will be appended automatically.", ListUtils::create("advanced")); + "A serial number for each invocation will be appended automatically.", {"advanced"}); defaults_.setValue("dump_pairs", "", "[DEBUG] If non-empty, base filename where the individual hashed pairs will be dumped to (large!). " - "A serial number for each invocation will be appended automatically.", ListUtils::create("advanced")); + "A serial number for each invocation will be appended automatically.", {"advanced"}); defaultsToParam_(); } @@ -786,7 +786,7 @@ namespace OpenMS if (param_.getValue("dump_buckets") != "") { do_dump_buckets = true; - dump_buckets_basename = param_.getValue("dump_buckets"); + dump_buckets_basename = param_.getValue("dump_buckets").toString(); } setProgress(++actual_progress); @@ -796,7 +796,7 @@ namespace OpenMS if (param_.getValue("dump_pairs") != "") { do_dump_pairs = true; - dump_pairs_basename = param_.getValue("dump_pairs"); + dump_pairs_basename = param_.getValue("dump_pairs").toString(); } setProgress(++actual_progress); diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/PoseClusteringShiftSuperimposer.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/PoseClusteringShiftSuperimposer.cpp index afac76c5033..e9318d93f8b 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/PoseClusteringShiftSuperimposer.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/PoseClusteringShiftSuperimposer.cpp @@ -70,14 +70,14 @@ namespace OpenMS defaults_.setMinFloat("shift_bucket_size", 0.); defaults_.setValue("max_shift", 1000.0, "Maximal shift which is considered during histogramming. " - "This applies for both directions.", ListUtils::create("advanced")); + "This applies for both directions.", {"advanced"}); defaults_.setMinFloat("max_shift", 0.); defaults_.setValue("dump_buckets", "", "[DEBUG] If non-empty, base filename where hash table buckets will be dumped to. " - "A serial number for each invocation will be appended automatically.", ListUtils::create("advanced")); + "A serial number for each invocation will be appended automatically.", {"advanced"}); defaults_.setValue("dump_pairs", "", "[DEBUG] If non-empty, base filename where the individual hashed pairs will be dumped to (large!). " - "A serial number for each invocation will be appended automatically.", ListUtils::create("advanced")); + "A serial number for each invocation will be appended automatically.", {"advanced"}); defaultsToParam_(); return; @@ -117,7 +117,7 @@ namespace OpenMS if (param_.getValue("dump_buckets") != "") { do_dump_buckets = true; - dump_buckets_basename = param_.getValue("dump_buckets"); + dump_buckets_basename = param_.getValue("dump_buckets").toString(); } setProgress(++actual_progress); @@ -127,7 +127,7 @@ namespace OpenMS if (param_.getValue("dump_pairs") != "") { do_dump_pairs = true; - dump_pairs_basename = param_.getValue("dump_pairs"); + dump_pairs_basename = param_.getValue("dump_pairs").toString(); } setProgress(++actual_progress); diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/QTClusterFinder.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/QTClusterFinder.cpp index 13a5dcb51b9..7902d510ad6 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/QTClusterFinder.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/QTClusterFinder.cpp @@ -55,7 +55,7 @@ namespace OpenMS setName(getProductName()); defaults_.setValue("use_identifications", "false", "Never link features that are annotated with different peptides (only the best hit per peptide identification is taken into account)."); - defaults_.setValidStrings("use_identifications", ListUtils::create("true,false")); + defaults_.setValidStrings("use_identifications", {"true","false"}); defaults_.setValue("nr_partitions", 100, "How many partitions in m/z space should be used for the algorithm (more partitions means faster runtime and more memory efficient execution)."); defaults_.setMinInt("nr_partitions", 1); defaults_.setValue("min_nr_diffs_per_bin", 50, "If IDs are used: How many differences from matching IDs should be used to calculate a linking tolerance for unIDed features in an RT region. RT regions will be extended until that number is reached."); @@ -82,7 +82,7 @@ namespace OpenMS throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, msg); } - use_IDs_ = String(param_.getValue("use_identifications")) == "true"; + use_IDs_ = param_.getValue("use_identifications").toBool(); nr_partitions_ = param_.getValue("nr_partitions"); min_nr_diffs_per_bin_ = param_.getValue("min_nr_diffs_per_bin"); min_score_ = param_.getValue("min_IDscore_forTolCalc"); diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/SimplePairFinder.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/SimplePairFinder.cpp index 69aaecbcf02..7fd2083bad4 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/SimplePairFinder.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/SimplePairFinder.cpp @@ -42,11 +42,11 @@ namespace OpenMS //set the name for DefaultParamHandler error messages setName(getProductName()); - defaults_.setValue("similarity:diff_intercept:RT", 1.0, "This parameter controls the asymptotic decay rate for large differences (for more details see the similarity measurement).", ListUtils::create("advanced")); - defaults_.setValue("similarity:diff_intercept:MZ", 0.1, "This parameter controls the asymptotic decay rate for large differences (for more details see the similarity measurement).", ListUtils::create("advanced")); - defaults_.setValue("similarity:diff_exponent:RT", 2.0, "This parameter is important for small differences (for more details see the similarity measurement).", ListUtils::create("advanced")); - defaults_.setValue("similarity:diff_exponent:MZ", 1.0, "This parameter is important for small differences (for more details see the similarity measurement).", ListUtils::create("advanced")); - defaults_.setValue("similarity:pair_min_quality", 0.01, "Minimum required pair quality.", ListUtils::create("advanced")); + defaults_.setValue("similarity:diff_intercept:RT", 1.0, "This parameter controls the asymptotic decay rate for large differences (for more details see the similarity measurement).", {"advanced"}); + defaults_.setValue("similarity:diff_intercept:MZ", 0.1, "This parameter controls the asymptotic decay rate for large differences (for more details see the similarity measurement).", {"advanced"}); + defaults_.setValue("similarity:diff_exponent:RT", 2.0, "This parameter is important for small differences (for more details see the similarity measurement).", {"advanced"}); + defaults_.setValue("similarity:diff_exponent:MZ", 1.0, "This parameter is important for small differences (for more details see the similarity measurement).", {"advanced"}); + defaults_.setValue("similarity:pair_min_quality", 0.01, "Minimum required pair quality.", {"advanced"}); Base::defaultsToParam_(); } diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/StablePairFinder.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/StablePairFinder.cpp index 38e3f05d6af..a7a062d74c7 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/StablePairFinder.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/StablePairFinder.cpp @@ -59,7 +59,7 @@ namespace OpenMS defaults_.setMinFloat("second_nearest_gap", 1.0); defaults_.setValue("use_identifications", "false", "Never link features that are annotated with different peptides (features without ID's always match; only the best hit per peptide identification is considered)."); - defaults_.setValidStrings("use_identifications", ListUtils::create("true,false")); + defaults_.setValidStrings("use_identifications", {"true","false"}); defaults_.insert("", FeatureDistance().getDefaults()); @@ -71,7 +71,7 @@ namespace OpenMS V_("@@@ StablePairFinder::updateMembers_()"); second_nearest_gap_ = param_.getValue("second_nearest_gap"); - use_IDs_ = String(param_.getValue("use_identifications")) == "true"; + use_IDs_ = param_.getValue("use_identifications").toBool(); } void StablePairFinder::run(const std::vector& input_maps, diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModel.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModel.cpp index 4c6f86e3467..08214067b08 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModel.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModel.cpp @@ -61,8 +61,8 @@ namespace OpenMS y_datum_min_ = params_.exists("y_datum_min") ? (double)params_.getValue("y_datum_min") : 1e-15; y_datum_max_ = params_.exists("y_datum_max") ? (double)params_.getValue("y_datum_max") : 1e15; - y_weight_ = params_.exists("y_weight") ? (String)params_.getValue("y_weight") : ""; - x_weight_ = params_.exists("x_weight") ? (String)params_.getValue("x_weight") : ""; + y_weight_ = params_.exists("y_weight") ? String(params_.getValue("y_weight").toString()) : ""; + x_weight_ = params_.exists("x_weight") ? String(params_.getValue("x_weight").toString()) : ""; std::vector valid_x_weights = getValidXWeights(); std::vector valid_y_weights = getValidYWeights(); diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelBSpline.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelBSpline.cpp index fe42e85b2d5..ceb3074cbaa 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelBSpline.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelBSpline.cpp @@ -34,6 +34,7 @@ #include #include +#include using namespace std; @@ -88,7 +89,7 @@ namespace OpenMS } // extrapolation: - String extrapolate = params_.getValue("extrapolate"); + std::string extrapolate = params_.getValue("extrapolate"); if (extrapolate == "b_spline") { extrapolate_ = EX_BSPLINE; @@ -163,7 +164,7 @@ namespace OpenMS params.setValue("num_nodes", 5, "Number of nodes for B-spline fitting. Overrides 'wavelength' if set (to two or greater). A lower value means more smoothing."); params.setMinInt("num_nodes", 0); params.setValue("extrapolate", "linear", "Method to use for extrapolation beyond the original data range. 'linear': Linear extrapolation using the slope of the B-spline at the corresponding endpoint. 'b_spline': Use the B-spline (as for interpolation). 'constant': Use the constant value of the B-spline at the corresponding endpoint. 'global_linear': Use a linear fit through the data (which will most probably introduce discontinuities at the ends of the data range)."); - params.setValidStrings("extrapolate", ListUtils::create("linear,b_spline,constant,global_linear")); + params.setValidStrings("extrapolate", {"linear","b_spline","constant","global_linear"}); params.setValue("boundary_condition", 2, "Boundary condition at B-spline endpoints: 0 (value zero), 1 (first derivative zero) or 2 (second derivative zero)"); params.setMinInt("boundary_condition", 0); params.setMaxInt("boundary_condition", 2); diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelInterpolated.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelInterpolated.cpp index 5ba978f3748..59628b57919 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelInterpolated.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelInterpolated.cpp @@ -32,6 +32,10 @@ // $Authors: Stephan Aiche $ // -------------------------------------------------------------------------- +#include +#include +#include + #include // Spline2dInterpolator @@ -259,7 +263,7 @@ namespace OpenMS // choose the actual interpolation type - const String interpolation_type = params_.getValue("interpolation_type"); + const String interpolation_type = params_.getValue("interpolation_type").toString(); if (interpolation_type == "linear") { interp_ = new LinearInterpolator(); @@ -282,7 +286,7 @@ namespace OpenMS interp_->init(x_, y_); // linear model for extrapolation: - const String extrapolation_type = params_.getValue("extrapolation_type"); + const String extrapolation_type = params_.getValue("extrapolation_type").toString(); if (extrapolation_type == "global-linear") { std::vector bloated_data{}; @@ -337,7 +341,7 @@ namespace OpenMS preprocessDataPoints_(data); // choose the actual interpolation type - const String interpolation_type = params_.getValue("interpolation_type"); + const String interpolation_type = params_.getValue("interpolation_type").toString(); if (interpolation_type == "linear") { interp_ = new LinearInterpolator(); @@ -360,7 +364,7 @@ namespace OpenMS interp_->init(x_, y_); // linear model for extrapolation: - const String extrapolation_type = params_.getValue("extrapolation_type"); + const String extrapolation_type = params_.getValue("extrapolation_type").toString(); if (extrapolation_type == "global-linear") { lm_front_ = new TransformationModelLinear(data, Param()); @@ -422,11 +426,9 @@ namespace OpenMS { params.clear(); params.setValue("interpolation_type", "cspline", "Type of interpolation to apply."); - StringList types = ListUtils::create("linear,cspline,akima"); - params.setValidStrings("interpolation_type", types); + params.setValidStrings("interpolation_type", {"linear","cspline","akima"}); params.setValue("extrapolation_type", "two-point-linear", "Type of extrapolation to apply: two-point-linear: use the first and last data point to build a single linear model, four-point-linear: build two linear models on both ends using the first two / last two points, global-linear: use all points to build a single linear model. Note that global-linear may not be continuous at the border."); - StringList etypes = ListUtils::create("two-point-linear,four-point-linear,global-linear"); - params.setValidStrings("extrapolation_type", etypes); + params.setValidStrings("extrapolation_type", {"two-point-linear","four-point-linear","global-linear"}); } } // namespace diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelLinear.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelLinear.cpp index fec920f8061..1cf425bd63c 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelLinear.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelLinear.cpp @@ -33,6 +33,7 @@ // -------------------------------------------------------------------------- #include +#include #include #include @@ -154,13 +155,13 @@ namespace OpenMS params.setValue("symmetric_regression", "false", "Perform linear regression" " on 'y - x' vs. 'y + x', instead of on 'y' vs. 'x'."); params.setValidStrings("symmetric_regression", - ListUtils::create("true,false")); + {"true","false"}); params.setValue("x_weight", "", "Weight x values"); params.setValidStrings("x_weight", - ListUtils::create("1/x,1/x2,ln(x),")); + {"1/x","1/x2","ln(x)",""}); params.setValue("y_weight", "", "Weight y values"); params.setValidStrings("y_weight", - ListUtils::create("1/y,1/y2,ln(y),")); + {"1/y","1/y2","ln(y)",""}); params.setValue("x_datum_min", 1e-15, "Minimum x value"); params.setValue("x_datum_max", 1e15, "Maximum x value"); params.setValue("y_datum_min", 1e-15, "Minimum y value"); diff --git a/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelLowess.cpp b/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelLowess.cpp index 05a6e2561db..3f479fc20cb 100644 --- a/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelLowess.cpp +++ b/src/openms/source/ANALYSIS/MAPMATCHING/TransformationModelLowess.cpp @@ -131,11 +131,10 @@ namespace OpenMS params.setValue("delta", -1.0, "Nonnegative parameter which may be used to save computations (recommended value is 0.01 of the range of the input, e.g. for data ranging from 1000 seconds to 2000 seconds, it could be set to 10). Setting a negative value will automatically do this."); params.setValue("interpolation_type", "cspline", "Method to use for interpolation between datapoints computed by lowess. 'linear': Linear interpolation. 'cspline': Use the cubic spline for interpolation. 'akima': Use an akima spline for interpolation"); - params.setValidStrings("interpolation_type", ListUtils::create("linear,cspline,akima")); + params.setValidStrings("interpolation_type", {"linear","cspline","akima"}); params.setValue("extrapolation_type", "four-point-linear", "Method to use for extrapolation outside the data range. 'two-point-linear': Uses a line through the first and last point to extrapolate. 'four-point-linear': Uses a line through the first and second point to extrapolate in front and and a line through the last and second-to-last point in the end. 'global-linear': Uses a linear regression to fit a line through all data points and use it for interpolation."); - StringList etypes = ListUtils::create("two-point-linear,four-point-linear,global-linear"); - params.setValidStrings("extrapolation_type", etypes); + params.setValidStrings("extrapolation_type", {"two-point-linear","four-point-linear","global-linear"}); } } diff --git a/src/openms/source/ANALYSIS/MRM/MRMFragmentSelection.cpp b/src/openms/source/ANALYSIS/MRM/MRMFragmentSelection.cpp index 15c4a1cc00e..b9ffa0ee7c2 100644 --- a/src/openms/source/ANALYSIS/MRM/MRMFragmentSelection.cpp +++ b/src/openms/source/ANALYSIS/MRM/MRMFragmentSelection.cpp @@ -49,11 +49,11 @@ namespace OpenMS defaults_.setValue("min_mz", 400.0, "Minimal m/z value that is allowed for selection."); defaults_.setValue("max_mz", 1200.0, "Maximal m/z value that is allowed for selection."); defaults_.setValue("consider_names", "true", "Should names be considered when selecting ions?"); - defaults_.setValidStrings("consider_names", ListUtils::create("true,false")); + defaults_.setValidStrings("consider_names", {"true","false"}); defaults_.setValue("allow_loss_ions", "false", "Should loss ions allowed to be selected?"); - defaults_.setValidStrings("allow_loss_ions", ListUtils::create("true,false")); - defaults_.setValue("allowed_ion_types", ListUtils::create("y"), "The one-character-typenames of the ion types allowed"); - defaults_.setValue("allowed_charges", ListUtils::create("1"), "List of allowed charge states for selection."); + defaults_.setValidStrings("allow_loss_ions", {"true","false"}); + defaults_.setValue("allowed_ion_types", std::vector{"y"}, "The one-character-typenames of the ion types allowed"); + defaults_.setValue("allowed_charges", std::vector{"1"}, "List of allowed charge states for selection."); defaultsToParam_(); } @@ -113,11 +113,11 @@ namespace OpenMS bool MRMFragmentSelection::peakselectionIsAllowed_(const String& name, const int charge) { - StringList allowed_charges = param_.getValue("allowed_charges"); + StringList allowed_charges = ListUtils::toStringList(param_.getValue("allowed_charges")); if (!name.empty()) { - StringList allowed_types = param_.getValue("allowed_ion_types"); + StringList allowed_types = ListUtils::toStringList(param_.getValue("allowed_ion_types")); bool type_found(false); for (StringList::const_iterator it = allowed_types.begin(); it != allowed_types.end(); ++it) { diff --git a/src/openms/source/ANALYSIS/OPENSWATH/DIAScoring.cpp b/src/openms/source/ANALYSIS/OPENSWATH/DIAScoring.cpp index 8e52faa851f..e95f227201d 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/DIAScoring.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/DIAScoring.cpp @@ -66,9 +66,9 @@ namespace OpenMS defaults_.setValue("dia_extraction_window", 0.05, "DIA extraction window in Th or ppm."); defaults_.setMinFloat("dia_extraction_window", 0.0); defaults_.setValue("dia_extraction_unit", "Th", "DIA extraction window unit"); - defaults_.setValidStrings("dia_extraction_unit", ListUtils::create("Th,ppm")); + defaults_.setValidStrings("dia_extraction_unit", {"Th","ppm"}); defaults_.setValue("dia_centroided", "false", "Use centroided DIA data."); - defaults_.setValidStrings("dia_centroided", ListUtils::create("true,false")); + defaults_.setValidStrings("dia_centroided", {"true","false"}); defaults_.setValue("dia_byseries_intensity_min", 300.0, "DIA b/y series minimum intensity to consider."); defaults_.setMinFloat("dia_byseries_intensity_min", 0.0); defaults_.setValue("dia_byseries_ppm_diff", 10.0, "DIA b/y series minimal difference in ppm to consider."); diff --git a/src/openms/source/ANALYSIS/OPENSWATH/MRMDecoy.cpp b/src/openms/source/ANALYSIS/OPENSWATH/MRMDecoy.cpp index 15fff42c685..db2d985cb63 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/MRMDecoy.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/MRMDecoy.cpp @@ -48,11 +48,11 @@ namespace OpenMS { defaults_.setValue("non_shuffle_pattern", "KRP", "Residues to not shuffle (keep at a constant position when shuffling). Default is 'KPR' to not shuffle lysine, arginine and proline."); - defaults_.setValue("keepPeptideNTerm", "true", "Whether to keep peptide N terminus constant when shuffling / reversing.", ListUtils::create("advanced")); - defaults_.setValidStrings("keepPeptideNTerm", ListUtils::create("true,false")); + defaults_.setValue("keepPeptideNTerm", "true", "Whether to keep peptide N terminus constant when shuffling / reversing.", {"advanced"}); + defaults_.setValidStrings("keepPeptideNTerm", {"true","false"}); - defaults_.setValue("keepPeptideCTerm", "true", "Whether to keep peptide C terminus constant when shuffling / reversing.", ListUtils::create("advanced")); - defaults_.setValidStrings("keepPeptideCTerm", ListUtils::create("true,false")); + defaults_.setValue("keepPeptideCTerm", "true", "Whether to keep peptide C terminus constant when shuffling / reversing.", {"advanced"}); + defaults_.setValidStrings("keepPeptideCTerm", {"true","false"}); // write defaults into Param object param_ defaultsToParam_(); @@ -60,7 +60,7 @@ namespace OpenMS void MRMDecoy::updateMembers_() { - keep_const_pattern_ = param_.getValue("non_shuffle_pattern"); + keep_const_pattern_ = param_.getValue("non_shuffle_pattern").toString(); keepN_ = param_.getValue("keepPeptideNTerm").toBool(); keepC_ = param_.getValue("keepPeptideCTerm").toBool(); } diff --git a/src/openms/source/ANALYSIS/OPENSWATH/MRMFeatureFilter.cpp b/src/openms/source/ANALYSIS/OPENSWATH/MRMFeatureFilter.cpp index 5849fc892aa..f28c66e4ca9 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/MRMFeatureFilter.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/MRMFeatureFilter.cpp @@ -67,8 +67,8 @@ namespace OpenMS { params.clear(); - params.setValue("flag_or_filter", "flag", "Flag or Filter (i.e., remove) Components or transitions that do not pass the QC.", ListUtils::create("advanced")); - params.setValidStrings("flag_or_filter", ListUtils::create("flag,filter")); + params.setValue("flag_or_filter", "flag", "Flag or Filter (i.e., remove) Components or transitions that do not pass the QC.", {"advanced"}); + params.setValidStrings("flag_or_filter", {"flag","filter"}); } void MRMFeatureFilter::updateMembers_() diff --git a/src/openms/source/ANALYSIS/OPENSWATH/MRMFeatureFinderScoring.cpp b/src/openms/source/ANALYSIS/OPENSWATH/MRMFeatureFinderScoring.cpp index 393395af33f..7dd1dacb3eb 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/MRMFeatureFinderScoring.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/MRMFeatureFinderScoring.cpp @@ -90,23 +90,23 @@ namespace OpenMS defaults_.setValue("stop_report_after_feature", -1, "Stop reporting after feature (ordered by quality; -1 means do not stop)."); defaults_.setValue("rt_extraction_window", -1.0, "Only extract RT around this value (-1 means extract over the whole range, a value of 500 means to extract around +/- 500 s of the expected elution). For this to work, the TraML input file needs to contain normalized RT values."); defaults_.setValue("rt_normalization_factor", 1.0, "The normalized RT is expected to be between 0 and 1. If your normalized RT has a different range, pass this here (e.g. it goes from 0 to 100, set this value to 100)"); - defaults_.setValue("quantification_cutoff", 0.0, "Cutoff in m/z below which peaks should not be used for quantification any more", ListUtils::create("advanced")); + defaults_.setValue("quantification_cutoff", 0.0, "Cutoff in m/z below which peaks should not be used for quantification any more", {"advanced"}); defaults_.setMinFloat("quantification_cutoff", 0.0); - defaults_.setValue("write_convex_hull", "false", "Whether to write out all points of all features into the featureXML", ListUtils::create("advanced")); - defaults_.setValidStrings("write_convex_hull", ListUtils::create("true,false")); - defaults_.setValue("spectrum_addition_method", "simple", "For spectrum addition, either use simple concatenation or use peak resampling", ListUtils::create("advanced")); + defaults_.setValue("write_convex_hull", "false", "Whether to write out all points of all features into the featureXML", {"advanced"}); + defaults_.setValidStrings("write_convex_hull", {"true","false"}); + defaults_.setValue("spectrum_addition_method", "simple", "For spectrum addition, either use simple concatenation or use peak resampling", {"advanced"}); defaults_.setValidStrings("spectrum_addition_method", {"simple", "resample"}); - defaults_.setValue("add_up_spectra", 1, "Add up spectra around the peak apex (needs to be a non-even integer)", ListUtils::create("advanced")); + defaults_.setValue("add_up_spectra", 1, "Add up spectra around the peak apex (needs to be a non-even integer)", {"advanced"}); defaults_.setMinInt("add_up_spectra", 1); - defaults_.setValue("spacing_for_spectra_resampling", 0.005, "If spectra are to be added, use this spacing to add them up", ListUtils::create("advanced")); + defaults_.setValue("spacing_for_spectra_resampling", 0.005, "If spectra are to be added, use this spacing to add them up", {"advanced"}); defaults_.setMinFloat("spacing_for_spectra_resampling", 0.0); defaults_.setValue("uis_threshold_sn", -1, "S/N threshold to consider identification transition (set to -1 to consider all)"); defaults_.setValue("uis_threshold_peak_area", 0, "Peak area threshold to consider identification transition (set to -1 to consider all)"); - defaults_.setValue("scoring_model", "default", "Scoring model to use", ListUtils::create("advanced")); - defaults_.setValidStrings("scoring_model", ListUtils::create("default,single_transition")); - defaults_.setValue("im_extra_drift", 0.0, "Extra drift time to extract for IM scoring (as a fraction, e.g. 0.25 means 25% extra on each side)", ListUtils::create("advanced")); + defaults_.setValue("scoring_model", "default", "Scoring model to use", {"advanced"}); + defaults_.setValidStrings("scoring_model", {"default","single_transition"}); + defaults_.setValue("im_extra_drift", 0.0, "Extra drift time to extract for IM scoring (as a fraction, e.g. 0.25 means 25% extra on each side)", {"advanced"}); defaults_.setMinFloat("im_extra_drift", 0.0); - defaults_.setValue("strict", "true", "Whether to error (true) or skip (false) if a transition in a transition group does not have a corresponding chromatogram.", ListUtils::create("advanced")); + defaults_.setValue("strict", "true", "Whether to error (true) or skip (false) if a transition in a transition group does not have a corresponding chromatogram.", {"advanced"}); defaults_.insert("TransitionGroupPicker:", MRMTransitionGroupPicker().getDefaults()); @@ -116,46 +116,46 @@ namespace OpenMS // One can turn on / off each score individually Param scores_to_use; - scores_to_use.setValue("use_shape_score", "true", "Use the shape score (this score measures the similarity in shape of the transitions using a cross-correlation)", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_shape_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_coelution_score", "true", "Use the coelution score (this score measures the similarity in coelution of the transitions using a cross-correlation)", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_coelution_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_rt_score", "true", "Use the retention time score (this score measure the difference in retention time)", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_rt_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_library_score", "true", "Use the library score", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_library_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_elution_model_score", "true", "Use the elution model (EMG) score (this score fits a gaussian model to the peak and checks the fit)", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_elution_model_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_intensity_score", "true", "Use the intensity score", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_intensity_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_nr_peaks_score", "true", "Use the number of peaks score", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_nr_peaks_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_total_xic_score", "true", "Use the total XIC score", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_total_xic_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_total_mi_score", "false", "Use the total MI score", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_total_mi_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_sn_score", "true", "Use the SN (signal to noise) score", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_sn_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_mi_score", "false", "Use the MI (mutual information) score", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_mi_score", ListUtils::create("true,false")); - scores_to_use.setValue("use_dia_scores", "true", "Use the DIA (SWATH) scores. If turned off, will not use fragment ion spectra for scoring.", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_dia_scores", ListUtils::create("true,false")); - scores_to_use.setValue("use_ms1_correlation", "false", "Use the correlation scores with the MS1 elution profiles", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_ms1_correlation", ListUtils::create("true,false")); - scores_to_use.setValue("use_sonar_scores", "false", "Use the scores for SONAR scans (scanning swath)", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_sonar_scores", ListUtils::create("true,false")); - scores_to_use.setValue("use_ion_mobility_scores", "false", "Use the scores for Ion Mobility scans", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_ion_mobility_scores", ListUtils::create("true,false")); - scores_to_use.setValue("use_ms1_fullscan", "false", "Use the full MS1 scan at the peak apex for scoring (ppm accuracy of precursor and isotopic pattern)", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_ms1_fullscan", ListUtils::create("true,false")); - scores_to_use.setValue("use_ms1_mi", "false", "Use the MS1 MI score", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_ms1_mi", ListUtils::create("true,false")); - scores_to_use.setValue("use_uis_scores", "false", "Use UIS scores for peptidoform identification", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_uis_scores", ListUtils::create("true,false")); - scores_to_use.setValue("use_ionseries_scores", "true", "Use MS2-level b/y ion-series scores for peptidoform identification", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_ionseries_scores", ListUtils::create("true,false")); - scores_to_use.setValue("use_ms2_isotope_scores", "true", "Use MS2-level isotope scores (pearson & manhattan) across product transitions (based on ID if annotated or averagine)", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_ms2_isotope_scores", ListUtils::create("true,false")); + scores_to_use.setValue("use_shape_score", "true", "Use the shape score (this score measures the similarity in shape of the transitions using a cross-correlation)", {"advanced"}); + scores_to_use.setValidStrings("use_shape_score", {"true","false"}); + scores_to_use.setValue("use_coelution_score", "true", "Use the coelution score (this score measures the similarity in coelution of the transitions using a cross-correlation)", {"advanced"}); + scores_to_use.setValidStrings("use_coelution_score", {"true","false"}); + scores_to_use.setValue("use_rt_score", "true", "Use the retention time score (this score measure the difference in retention time)", {"advanced"}); + scores_to_use.setValidStrings("use_rt_score", {"true","false"}); + scores_to_use.setValue("use_library_score", "true", "Use the library score", {"advanced"}); + scores_to_use.setValidStrings("use_library_score", {"true","false"}); + scores_to_use.setValue("use_elution_model_score", "true", "Use the elution model (EMG) score (this score fits a gaussian model to the peak and checks the fit)", {"advanced"}); + scores_to_use.setValidStrings("use_elution_model_score", {"true","false"}); + scores_to_use.setValue("use_intensity_score", "true", "Use the intensity score", {"advanced"}); + scores_to_use.setValidStrings("use_intensity_score", {"true","false"}); + scores_to_use.setValue("use_nr_peaks_score", "true", "Use the number of peaks score", {"advanced"}); + scores_to_use.setValidStrings("use_nr_peaks_score", {"true","false"}); + scores_to_use.setValue("use_total_xic_score", "true", "Use the total XIC score", {"advanced"}); + scores_to_use.setValidStrings("use_total_xic_score", {"true","false"}); + scores_to_use.setValue("use_total_mi_score", "false", "Use the total MI score", {"advanced"}); + scores_to_use.setValidStrings("use_total_mi_score", {"true","false"}); + scores_to_use.setValue("use_sn_score", "true", "Use the SN (signal to noise) score", {"advanced"}); + scores_to_use.setValidStrings("use_sn_score", {"true","false"}); + scores_to_use.setValue("use_mi_score", "false", "Use the MI (mutual information) score", {"advanced"}); + scores_to_use.setValidStrings("use_mi_score", {"true","false"}); + scores_to_use.setValue("use_dia_scores", "true", "Use the DIA (SWATH) scores. If turned off, will not use fragment ion spectra for scoring.", {"advanced"}); + scores_to_use.setValidStrings("use_dia_scores", {"true","false"}); + scores_to_use.setValue("use_ms1_correlation", "false", "Use the correlation scores with the MS1 elution profiles", {"advanced"}); + scores_to_use.setValidStrings("use_ms1_correlation", {"true","false"}); + scores_to_use.setValue("use_sonar_scores", "false", "Use the scores for SONAR scans (scanning swath)", {"advanced"}); + scores_to_use.setValidStrings("use_sonar_scores", {"true","false"}); + scores_to_use.setValue("use_ion_mobility_scores", "false", "Use the scores for Ion Mobility scans", {"advanced"}); + scores_to_use.setValidStrings("use_ion_mobility_scores", {"true","false"}); + scores_to_use.setValue("use_ms1_fullscan", "false", "Use the full MS1 scan at the peak apex for scoring (ppm accuracy of precursor and isotopic pattern)", {"advanced"}); + scores_to_use.setValidStrings("use_ms1_fullscan", {"true","false"}); + scores_to_use.setValue("use_ms1_mi", "false", "Use the MS1 MI score", {"advanced"}); + scores_to_use.setValidStrings("use_ms1_mi", {"true","false"}); + scores_to_use.setValue("use_uis_scores", "false", "Use UIS scores for peptidoform identification", {"advanced"}); + scores_to_use.setValidStrings("use_uis_scores", {"true","false"}); + scores_to_use.setValue("use_ionseries_scores", "true", "Use MS2-level b/y ion-series scores for peptidoform identification", {"advanced"}); + scores_to_use.setValidStrings("use_ionseries_scores", {"true","false"}); + scores_to_use.setValue("use_ms2_isotope_scores", "true", "Use MS2-level isotope scores (pearson & manhattan) across product transitions (based on ID if annotated or averagine)", {"advanced"}); + scores_to_use.setValidStrings("use_ms2_isotope_scores", {"true","false"}); defaults_.insert("Scores:", scores_to_use); // write defaults into Param object param_ @@ -1031,12 +1031,12 @@ namespace OpenMS quantification_cutoff_ = (double)param_.getValue("quantification_cutoff"); write_convex_hull_ = param_.getValue("write_convex_hull").toBool(); add_up_spectra_ = param_.getValue("add_up_spectra"); - spectrum_addition_method_ = param_.getValue("spectrum_addition_method"); + spectrum_addition_method_ = param_.getValue("spectrum_addition_method").toString(); spacing_for_spectra_resampling_ = param_.getValue("spacing_for_spectra_resampling"); im_extra_drift_ = (double)param_.getValue("im_extra_drift"); uis_threshold_sn_ = param_.getValue("uis_threshold_sn"); uis_threshold_peak_area_ = param_.getValue("uis_threshold_peak_area"); - scoring_model_ = param_.getValue("scoring_model"); + scoring_model_ = param_.getValue("scoring_model").toString(); sn_win_len_ = (double)param_.getValue("TransitionGroupPicker:PeakPickerMRM:sn_win_len"); sn_bin_count_ = (unsigned int)param_.getValue("TransitionGroupPicker:PeakPickerMRM:sn_bin_count"); diff --git a/src/openms/source/ANALYSIS/OPENSWATH/MRMRTNormalizer.cpp b/src/openms/source/ANALYSIS/OPENSWATH/MRMRTNormalizer.cpp index f73effe7f17..6622ff37efd 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/MRMRTNormalizer.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/MRMRTNormalizer.cpp @@ -166,8 +166,6 @@ namespace OpenMS rsq = lin_reg.getRSquared(); - std::cout << "rsq: " << rsq << " points: " << x.size() << std::endl; - if (rsq < rsq_limit) { std::vector residuals; diff --git a/src/openms/source/ANALYSIS/OPENSWATH/MRMTransitionGroupPicker.cpp b/src/openms/source/ANALYSIS/OPENSWATH/MRMTransitionGroupPicker.cpp index 7a979f6fde7..34a95c5d07c 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/MRMTransitionGroupPicker.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/MRMTransitionGroupPicker.cpp @@ -52,40 +52,40 @@ namespace OpenMS { defaults_.setValue("stop_after_feature", -1, "Stop finding after feature (ordered by intensity; -1 means do not stop)."); defaults_.setValue("stop_after_intensity_ratio", 0.0001, "Stop after reaching intensity ratio"); - defaults_.setValue("min_peak_width", -1.0, "Minimal peak width (s), discard all peaks below this value (-1 means no action).", ListUtils::create("advanced")); + defaults_.setValue("min_peak_width", -1.0, "Minimal peak width (s), discard all peaks below this value (-1 means no action).", {"advanced"}); - defaults_.setValue("peak_integration", "original", "Calculate the peak area and height either the smoothed or the raw chromatogram data.", ListUtils::create("advanced")); - defaults_.setValidStrings("peak_integration", ListUtils::create("original,smoothed")); + defaults_.setValue("peak_integration", "original", "Calculate the peak area and height either the smoothed or the raw chromatogram data.", {"advanced"}); + defaults_.setValidStrings("peak_integration", {"original","smoothed"}); - defaults_.setValue("background_subtraction", "none", "Remove background from peak signal using estimated noise levels. The 'original' method is only provided for historical purposes, please use the 'exact' method and set parameters using the PeakIntegrator: settings. The same original or smoothed chromatogram specified by peak_integration will be used for background estimation.", ListUtils::create("advanced")); - defaults_.setValidStrings("background_subtraction", ListUtils::create("none,original,exact")); + defaults_.setValue("background_subtraction", "none", "Remove background from peak signal using estimated noise levels. The 'original' method is only provided for historical purposes, please use the 'exact' method and set parameters using the PeakIntegrator: settings. The same original or smoothed chromatogram specified by peak_integration will be used for background estimation.", {"advanced"}); + defaults_.setValidStrings("background_subtraction", {"none","original","exact"}); - defaults_.setValue("recalculate_peaks", "false", "Tries to get better peak picking by looking at peak consistency of all picked peaks. Tries to use the consensus (median) peak border if the variation within the picked peaks is too large.", ListUtils::create("advanced")); - defaults_.setValidStrings("recalculate_peaks", ListUtils::create("true,false")); + defaults_.setValue("recalculate_peaks", "false", "Tries to get better peak picking by looking at peak consistency of all picked peaks. Tries to use the consensus (median) peak border if the variation within the picked peaks is too large.", {"advanced"}); + defaults_.setValidStrings("recalculate_peaks", {"true","false"}); - defaults_.setValue("use_precursors", "false", "Use precursor chromatogram for peak picking (note that this may lead to precursor signal driving the peak picking)", ListUtils::create("advanced")); - defaults_.setValidStrings("use_precursors", ListUtils::create("true,false")); + defaults_.setValue("use_precursors", "false", "Use precursor chromatogram for peak picking (note that this may lead to precursor signal driving the peak picking)", {"advanced"}); + defaults_.setValidStrings("use_precursors", {"true","false"}); - defaults_.setValue("use_consensus", "true", "Use consensus peak boundaries when computing transition group picking (if false, compute independent peak boundaries for each transition)", ListUtils::create("advanced")); - defaults_.setValidStrings("use_consensus", ListUtils::create("true,false")); + defaults_.setValue("use_consensus", "true", "Use consensus peak boundaries when computing transition group picking (if false, compute independent peak boundaries for each transition)", {"advanced"}); + defaults_.setValidStrings("use_consensus", {"true","false"}); - defaults_.setValue("recalculate_peaks_max_z", 1.0, "Determines the maximal Z-Score (difference measured in standard deviations) that is considered too large for peak boundaries. If the Z-Score is above this value, the median is used for peak boundaries (default value 1.0).", ListUtils::create("advanced")); + defaults_.setValue("recalculate_peaks_max_z", 1.0, "Determines the maximal Z-Score (difference measured in standard deviations) that is considered too large for peak boundaries. If the Z-Score is above this value, the median is used for peak boundaries (default value 1.0).", {"advanced"}); - defaults_.setValue("minimal_quality", -10000.0, "Only if compute_peak_quality is set, this parameter will not consider peaks below this quality threshold", ListUtils::create("advanced")); + defaults_.setValue("minimal_quality", -10000.0, "Only if compute_peak_quality is set, this parameter will not consider peaks below this quality threshold", {"advanced"}); - defaults_.setValue("resample_boundary", 15.0, "For computing peak quality, how many extra seconds should be sample left and right of the actual peak", ListUtils::create("advanced")); + defaults_.setValue("resample_boundary", 15.0, "For computing peak quality, how many extra seconds should be sample left and right of the actual peak", {"advanced"}); - defaults_.setValue("compute_peak_quality", "false", "Tries to compute a quality value for each peakgroup and detect outlier transitions. The resulting score is centered around zero and values above 0 are generally good and below -1 or -2 are usually bad.", ListUtils::create("advanced")); - defaults_.setValidStrings("compute_peak_quality", ListUtils::create("true,false")); + defaults_.setValue("compute_peak_quality", "false", "Tries to compute a quality value for each peakgroup and detect outlier transitions. The resulting score is centered around zero and values above 0 are generally good and below -1 or -2 are usually bad.", {"advanced"}); + defaults_.setValidStrings("compute_peak_quality", {"true","false"}); - defaults_.setValue("compute_peak_shape_metrics", "false", "Calculates various peak shape metrics (e.g., tailing) that can be used for downstream QC/QA.", ListUtils::create("advanced")); - defaults_.setValidStrings("compute_peak_shape_metrics", ListUtils::create("true,false")); + defaults_.setValue("compute_peak_shape_metrics", "false", "Calculates various peak shape metrics (e.g., tailing) that can be used for downstream QC/QA.", {"advanced"}); + defaults_.setValidStrings("compute_peak_shape_metrics", {"true","false"}); - defaults_.setValue("compute_total_mi", "false", "Compute mutual information metrics for individual transitions that can be used for OpenSWATH/IPF scoring.", ListUtils::create("advanced")); - defaults_.setValidStrings("compute_total_mi", ListUtils::create("true,false")); + defaults_.setValue("compute_total_mi", "false", "Compute mutual information metrics for individual transitions that can be used for OpenSWATH/IPF scoring.", {"advanced"}); + defaults_.setValidStrings("compute_total_mi", {"true","false"}); - defaults_.setValue("boundary_selection_method", "largest", "Method to use when selecting the best boundaries for peaks.", ListUtils::create("advanced")); - defaults_.setValidStrings("boundary_selection_method", ListUtils::create("largest,widest")); + defaults_.setValue("boundary_selection_method", "largest", "Method to use when selecting the best boundaries for peaks.", {"advanced"}); + defaults_.setValidStrings("boundary_selection_method", {"largest","widest"}); defaults_.insert("PeakPickerMRM:", PeakPickerMRM().getDefaults()); defaults_.insert("PeakIntegrator:", PeakIntegrator().getDefaults()); @@ -113,8 +113,8 @@ namespace OpenMS { stop_after_feature_ = (int)param_.getValue("stop_after_feature"); stop_after_intensity_ratio_ = (double)param_.getValue("stop_after_intensity_ratio"); - peak_integration_ = param_.getValue("peak_integration"); - background_subtraction_ = param_.getValue("background_subtraction"); + peak_integration_ = param_.getValue("peak_integration").toString(); + background_subtraction_ = param_.getValue("background_subtraction").toString(); recalculate_peaks_ = (bool)param_.getValue("recalculate_peaks").toBool(); use_precursors_ = (bool)param_.getValue("use_precursors").toBool(); use_consensus_ = (bool)param_.getValue("use_consensus").toBool(); @@ -125,7 +125,7 @@ namespace OpenMS min_qual_ = (double)param_.getValue("minimal_quality"); min_peak_width_ = (double)param_.getValue("min_peak_width"); resample_boundary_ = (double)param_.getValue("resample_boundary"); - boundary_selection_method_ = param_.getValue("boundary_selection_method"); + boundary_selection_method_ = param_.getValue("boundary_selection_method").toString(); picker_.setParameters(param_.copy("PeakPickerMRM:", true)); pi_.setParameters(param_.copy("PeakIntegrator:", true)); diff --git a/src/openms/source/ANALYSIS/OPENSWATH/OpenSwathWorkflow.cpp b/src/openms/source/ANALYSIS/OPENSWATH/OpenSwathWorkflow.cpp index 143456accf1..eede076da82 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/OpenSwathWorkflow.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/OpenSwathWorkflow.cpp @@ -203,7 +203,7 @@ namespace OpenMS // 5. Perform the outlier detection std::vector > pairs_corrected; - String outlier_method = irt_detection_param.getValue("outlierMethod"); + String outlier_method = irt_detection_param.getValue("outlierMethod").toString(); if (outlier_method == "iter_residual" || outlier_method == "iter_jackknife") { pairs_corrected = MRMRTNormalizer::removeOutliersIterative(pairs, min_rsq, min_coverage, @@ -289,7 +289,7 @@ namespace OpenMS model_params.setValue("symmetric_regression", "false"); model_params.setValue("span", irt_detection_param.getValue("lowess:span")); model_params.setValue("num_nodes", irt_detection_param.getValue("b_spline:num_nodes")); - String model_type = irt_detection_param.getValue("alignmentMethod"); + String model_type = irt_detection_param.getValue("alignmentMethod").toString(); trafo_out.fitModel(model_type, model_params); OPENMS_LOG_DEBUG << "Final RT mapping:" << std::endl; diff --git a/src/openms/source/ANALYSIS/OPENSWATH/PeakIntegrator.cpp b/src/openms/source/ANALYSIS/OPENSWATH/PeakIntegrator.cpp index e3a0bc44e79..ce30b858ee0 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/PeakIntegrator.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/PeakIntegrator.cpp @@ -110,19 +110,19 @@ namespace OpenMS params.clear(); params.setValue("integration_type", INTEGRATION_TYPE_INTENSITYSUM, "The integration technique to use in integratePeak() and estimateBackground() which uses either the summed intensity, integration by Simpson's rule or trapezoidal integration."); - params.setValidStrings("integration_type", ListUtils::create("intensity_sum,simpson,trapezoid")); + params.setValidStrings("integration_type", {"intensity_sum","simpson","trapezoid"}); params.setValue("baseline_type", BASELINE_TYPE_BASETOBASE, "The baseline type to use in estimateBackground() based on the peak boundaries. A rectangular baseline shape is computed based either on the minimal intensity of the peak boundaries, the maximum intensity or the average intensity (base_to_base)."); - params.setValidStrings("baseline_type", ListUtils::create("base_to_base,vertical_division,vertical_division_min,vertical_division_max")); + params.setValidStrings("baseline_type", {"base_to_base","vertical_division","vertical_division_min","vertical_division_max"}); params.setValue("fit_EMG", "false", "Fit the chromatogram/spectrum to the EMG peak model."); - params.setValidStrings("fit_EMG", ListUtils::create("false,true")); + params.setValidStrings("fit_EMG", {"false","true"}); } void PeakIntegrator::updateMembers_() { - integration_type_ = (String)param_.getValue("integration_type"); - baseline_type_ = (String)param_.getValue("baseline_type"); + integration_type_ = (String)param_.getValue("integration_type").toString(); + baseline_type_ = (String)param_.getValue("baseline_type").toString(); fit_EMG_ = param_.getValue("fit_EMG").toBool(); } diff --git a/src/openms/source/ANALYSIS/OPENSWATH/PeakPickerMRM.cpp b/src/openms/source/ANALYSIS/OPENSWATH/PeakPickerMRM.cpp index f5d6daaf5f6..3f5bed964bb 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/PeakPickerMRM.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/PeakPickerMRM.cpp @@ -49,7 +49,7 @@ namespace OpenMS defaults_.setValue("sgolay_polynomial_order", 3, "Order of the polynomial that is fitted."); defaults_.setValue("gauss_width", 50.0, "Gaussian width in seconds, estimated peak size."); defaults_.setValue("use_gauss", "true", "Use Gaussian filter for smoothing (alternative is Savitzky-Golay filter)"); - defaults_.setValidStrings("use_gauss", ListUtils::create("false,true")); + defaults_.setValidStrings("use_gauss", {"false","true"}); defaults_.setValue("peak_width", -1.0, "Force a certain minimal peak_width on the data (e.g. extend the peak at least by this amount on both sides) in seconds. -1 turns this feature off."); defaults_.setValue("signal_to_noise", 1.0, "Signal-to-noise threshold at which a peak will not be extended any more. Note that setting this too high (e.g. 1.0) can lead to peaks whose flanks are not fully captured."); @@ -58,13 +58,13 @@ namespace OpenMS defaults_.setValue("sn_win_len", 1000.0, "Signal to noise window length."); defaults_.setValue("sn_bin_count", 30, "Signal to noise bin count."); defaults_.setValue("write_sn_log_messages", "false", "Write out log messages of the signal-to-noise estimator in case of sparse windows or median in rightmost histogram bin"); - defaults_.setValidStrings("write_sn_log_messages", ListUtils::create("true,false")); + defaults_.setValidStrings("write_sn_log_messages", {"true","false"}); defaults_.setValue("remove_overlapping_peaks", "false", "Try to remove overlapping peaks during peak picking"); - defaults_.setValidStrings("remove_overlapping_peaks", ListUtils::create("false,true")); + defaults_.setValidStrings("remove_overlapping_peaks", {"false","true"}); defaults_.setValue("method", "corrected", "Which method to choose for chromatographic peak-picking (OpenSWATH legacy on raw data, corrected picking on smoothed chromatogram or Crawdad on smoothed chromatogram)."); - defaults_.setValidStrings("method", ListUtils::create("legacy,corrected,crawdad")); + defaults_.setValidStrings("method", {"legacy","corrected","crawdad"}); // write defaults into Param object param_ defaultsToParam_(); @@ -412,7 +412,7 @@ namespace OpenMS use_gauss_ = (bool)param_.getValue("use_gauss").toBool(); remove_overlapping_ = (bool)param_.getValue("remove_overlapping_peaks").toBool(); write_sn_log_messages_ = (bool)param_.getValue("write_sn_log_messages").toBool(); - method_ = (String)param_.getValue("method"); + method_ = (String)param_.getValue("method").toString(); if (method_ != "crawdad" && method_ != "corrected" && method_ != "legacy") { diff --git a/src/openms/source/ANALYSIS/OPENSWATH/SONARScoring.cpp b/src/openms/source/ANALYSIS/OPENSWATH/SONARScoring.cpp index ef287724b6a..d4deecb7e07 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/SONARScoring.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/SONARScoring.cpp @@ -55,9 +55,9 @@ namespace OpenMS defaults_.setValue("dia_extraction_window", 0.05, "DIA extraction window in Th or ppm."); defaults_.setMinFloat("dia_extraction_window", 0.0); defaults_.setValue("dia_extraction_unit", "Th", "DIA extraction window unit"); - defaults_.setValidStrings("dia_extraction_unit", ListUtils::create("Th,ppm")); + defaults_.setValidStrings("dia_extraction_unit", {"Th","ppm"}); defaults_.setValue("dia_centroided", "false", "Use centroided DIA data."); - defaults_.setValidStrings("dia_centroided", ListUtils::create("true,false")); + defaults_.setValidStrings("dia_centroided", {"true","false"}); // write defaults into Param object param_ defaultsToParam_(); diff --git a/src/openms/source/ANALYSIS/OPENSWATH/SwathMapMassCorrection.cpp b/src/openms/source/ANALYSIS/OPENSWATH/SwathMapMassCorrection.cpp index b2159a9d436..1a42eb32c4f 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/SwathMapMassCorrection.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/SwathMapMassCorrection.cpp @@ -85,15 +85,15 @@ namespace OpenMS DefaultParamHandler("SwathMapMassCorrection") { defaults_.setValue("mz_extraction_window", -1.0, "M/z extraction window width"); - defaults_.setValue("mz_extraction_window_ppm", "false", "Whether m/z extraction is in ppm", ListUtils::create("advanced")); - defaults_.setValidStrings("mz_extraction_window_ppm", ListUtils::create("true,false")); - defaults_.setValue("ms1_im_calibration", "false", "Whether to use MS1 precursor data for the ion mobility calibration (default = false, uses MS2 / fragment ions for calibration)", ListUtils::create("advanced")); - defaults_.setValidStrings("ms1_im_calibration", ListUtils::create("true,false")); + defaults_.setValue("mz_extraction_window_ppm", "false", "Whether m/z extraction is in ppm", {"advanced"}); + defaults_.setValidStrings("mz_extraction_window_ppm", {"true","false"}); + defaults_.setValue("ms1_im_calibration", "false", "Whether to use MS1 precursor data for the ion mobility calibration (default = false, uses MS2 / fragment ions for calibration)", {"advanced"}); + defaults_.setValidStrings("ms1_im_calibration", {"true","false"}); defaults_.setValue("im_extraction_window", -1.0, "Ion mobility extraction window width"); defaults_.setValue("mz_correction_function", "none", "Type of normalization function for m/z calibration."); - defaults_.setValidStrings("mz_correction_function", ListUtils::create("none,regression_delta_ppm,unweighted_regression,weighted_regression,quadratic_regression,weighted_quadratic_regression,weighted_quadratic_regression_delta_ppm,quadratic_regression_delta_ppm")); + defaults_.setValidStrings("mz_correction_function", {"none","regression_delta_ppm","unweighted_regression","weighted_regression","quadratic_regression","weighted_quadratic_regression","weighted_quadratic_regression_delta_ppm","quadratic_regression_delta_ppm"}); defaults_.setValue("im_correction_function", "linear", "Type of normalization function for IM calibration."); - defaults_.setValidStrings("im_correction_function", ListUtils::create("none,linear")); + defaults_.setValidStrings("im_correction_function", {"none","linear"}); defaults_.setValue("debug_im_file", "", "Debug file for Ion Mobility calibration."); defaults_.setValue("debug_mz_file", "", "Debug file for m/z calibration."); @@ -108,10 +108,10 @@ namespace OpenMS mz_extraction_window_ppm_ = param_.getValue("mz_extraction_window_ppm") == "true"; ms1_im_ = param_.getValue("ms1_im_calibration") == "true"; im_extraction_window_ = (double)param_.getValue("im_extraction_window"); - mz_correction_function_ = param_.getValue("mz_correction_function"); - im_correction_function_ = param_.getValue("im_correction_function"); - debug_mz_file_ = param_.getValue("debug_mz_file"); - debug_im_file_ = param_.getValue("debug_im_file"); + mz_correction_function_ = param_.getValue("mz_correction_function").toString(); + im_correction_function_ = param_.getValue("im_correction_function").toString(); + debug_mz_file_ = param_.getValue("debug_mz_file").toString(); + debug_im_file_ = param_.getValue("debug_im_file").toString(); } void SwathMapMassCorrection::correctIM( diff --git a/src/openms/source/ANALYSIS/OPENSWATH/TargetedSpectraExtractor.cpp b/src/openms/source/ANALYSIS/OPENSWATH/TargetedSpectraExtractor.cpp index 313abea2a41..e45c19d8fd6 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/TargetedSpectraExtractor.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/TargetedSpectraExtractor.cpp @@ -112,10 +112,10 @@ namespace OpenMS ); params.setValue("mz_unit_is_Da", "true", "Unit to use for mz_tolerance_ and fwhm_threshold_: true for Da, false for ppm."); - params.setValidStrings("mz_unit_is_Da", ListUtils::create("false,true")); + params.setValidStrings("mz_unit_is_Da", {"false","true"}); params.setValue("use_gauss", "true", "Use Gaussian filter for smoothing (alternative is Savitzky-Golay filter)"); - params.setValidStrings("use_gauss", ListUtils::create("false,true")); + params.setValidStrings("use_gauss", {"false","true"}); params.setValue("peak_height_min", 0.0, "Used in pickSpectrum(), a peak's intensity needs to be >= peak_height_min_ for it to be picked."); params.setMinFloat("peak_height_min", 0.0); diff --git a/src/openms/source/ANALYSIS/OPENSWATH/TransitionTSVFile.cpp b/src/openms/source/ANALYSIS/OPENSWATH/TransitionTSVFile.cpp index 0520b61c6af..a7713d333d0 100644 --- a/src/openms/source/ANALYSIS/OPENSWATH/TransitionTSVFile.cpp +++ b/src/openms/source/ANALYSIS/OPENSWATH/TransitionTSVFile.cpp @@ -111,12 +111,12 @@ namespace OpenMS TransitionTSVFile::TransitionTSVFile() : DefaultParamHandler("TransitionTSVFile") { - defaults_.setValue("retentionTimeInterpretation", "iRT", "How to interpret the provided retention time (the retention time column can either be interpreted to be in iRT, minutes or seconds)", ListUtils::create("advanced")); - defaults_.setValidStrings("retentionTimeInterpretation", ListUtils::create("iRT,seconds,minutes")); - defaults_.setValue("override_group_label_check", "false", "Override an internal check that assures that all members of the same PeptideGroupLabel have the same PeptideSequence (this ensures that only different isotopic forms of the same peptide can be grouped together in the same label group). Only turn this off if you know what you are doing.", ListUtils::create("advanced")); - defaults_.setValidStrings("override_group_label_check", ListUtils::create("true,false")); - defaults_.setValue("force_invalid_mods", "false", "Force reading even if invalid modifications are encountered (OpenMS may not recognize the modification)", ListUtils::create("advanced")); - defaults_.setValidStrings("force_invalid_mods", ListUtils::create("true,false")); + defaults_.setValue("retentionTimeInterpretation", "iRT", "How to interpret the provided retention time (the retention time column can either be interpreted to be in iRT, minutes or seconds)", {"advanced"}); + defaults_.setValidStrings("retentionTimeInterpretation", {"iRT","seconds","minutes"}); + defaults_.setValue("override_group_label_check", "false", "Override an internal check that assures that all members of the same PeptideGroupLabel have the same PeptideSequence (this ensures that only different isotopic forms of the same peptide can be grouped together in the same label group). Only turn this off if you know what you are doing.", {"advanced"}); + defaults_.setValidStrings("override_group_label_check", {"true","false"}); + defaults_.setValue("force_invalid_mods", "false", "Force reading even if invalid modifications are encountered (OpenMS may not recognize the modification)", {"advanced"}); + defaults_.setValidStrings("force_invalid_mods", {"true","false"}); // write defaults into Param object param_ defaultsToParam_(); @@ -129,7 +129,7 @@ namespace OpenMS void TransitionTSVFile::updateMembers_() { - retentionTimeInterpretation_ = param_.getValue("retentionTimeInterpretation"); + retentionTimeInterpretation_ = param_.getValue("retentionTimeInterpretation").toString(); override_group_label_check_ = param_.getValue("override_group_label_check").toBool(); force_invalid_mods_ = param_.getValue("force_invalid_mods").toBool(); } diff --git a/src/openms/source/ANALYSIS/QUANTITATION/AbsoluteQuantitation.cpp b/src/openms/source/ANALYSIS/QUANTITATION/AbsoluteQuantitation.cpp index 70a15cf3b76..00126ad5e37 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/AbsoluteQuantitation.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/AbsoluteQuantitation.cpp @@ -80,13 +80,13 @@ namespace OpenMS defaults_.setValue("max_iters", 100, "The maximum number of iterations to find an optimal set of calibration curve points and parameters."); defaults_.setValue("outlier_detection_method", "iter_jackknife", "Outlier detection method to find and remove bad calibration points."); - defaults_.setValidStrings("outlier_detection_method", ListUtils::create("iter_jackknife,iter_residual")); + defaults_.setValidStrings("outlier_detection_method", {"iter_jackknife","iter_residual"}); defaults_.setValue("use_chauvenet", "true", "Whether to only remove outliers that fulfill Chauvenet's criterion for outliers (otherwise it will remove any outlier candidate regardless of the criterion)."); - defaults_.setValidStrings("use_chauvenet", ListUtils::create("true,false")); + defaults_.setValidStrings("use_chauvenet", {"true","false"}); defaults_.setValue("optimization_method", "iterative", "Calibrator optimization method to find the best set of calibration points for each method."); - defaults_.setValidStrings("optimization_method", ListUtils::create("iterative")); + defaults_.setValidStrings("optimization_method", {"iterative"}); // write defaults into Param object param_ defaultsToParam_(); @@ -99,9 +99,9 @@ namespace OpenMS max_bias_ = (double)param_.getValue("max_bias"); min_correlation_coefficient_ = (double)param_.getValue("min_correlation_coefficient"); max_iters_ = (size_t)param_.getValue("max_iters"); - outlier_detection_method_ = param_.getValue("outlier_detection_method"); + outlier_detection_method_ = param_.getValue("outlier_detection_method").toString(); use_chauvenet_ = (bool)param_.getValue("use_chauvenet").toBool(); - optimization_method_ = param_.getValue("optimization_method"); + optimization_method_ = param_.getValue("optimization_method").toString(); } AbsoluteQuantitation::~AbsoluteQuantitation() diff --git a/src/openms/source/ANALYSIS/QUANTITATION/IsobaricChannelExtractor.cpp b/src/openms/source/ANALYSIS/QUANTITATION/IsobaricChannelExtractor.cpp index 4828ff333d7..2458453eb72 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/IsobaricChannelExtractor.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/IsobaricChannelExtractor.cpp @@ -163,7 +163,7 @@ namespace OpenMS void IsobaricChannelExtractor::setDefaultParams_() { defaults_.setValue("select_activation", Precursor::NamesOfActivationMethod[Precursor::HCID], "Operate only on MSn scans where any of its precursors features a certain activation method (e.g., usually HCD for iTRAQ). Set to empty string if you want to disable filtering."); - StringList activation_list; + std::vector activation_list; activation_list.insert(activation_list.begin(), Precursor::NamesOfActivationMethod, Precursor::NamesOfActivationMethod + Precursor::SIZE_OF_ACTIVATIONMETHOD - 1); activation_list.push_back(""); // allow disabling this @@ -177,13 +177,13 @@ namespace OpenMS defaults_.setMinFloat("min_precursor_intensity", 0.0); defaults_.setValue("keep_unannotated_precursor", "true", "Flag if precursor with missing intensity value or missing precursor spectrum should be included or not."); - defaults_.setValidStrings("keep_unannotated_precursor", ListUtils::create("true,false")); + defaults_.setValidStrings("keep_unannotated_precursor", {"true","false"}); defaults_.setValue("min_reporter_intensity", 0.0, "Minimum intensity of the individual reporter ions to be extracted."); defaults_.setMinFloat("min_reporter_intensity", 0.0); defaults_.setValue("discard_low_intensity_quantifications", "false", "Remove all reporter intensities if a single reporter is below the threshold given in 'min_reporter_intensity'."); - defaults_.setValidStrings("discard_low_intensity_quantifications", ListUtils::create("true,false")); + defaults_.setValidStrings("discard_low_intensity_quantifications", {"true","false"}); defaults_.setValue("min_precursor_purity", 0.0, "Minimum fraction of the total intensity in the isolation window of the precursor spectrum attributable to the selected precursor."); defaults_.setMinFloat("min_precursor_purity", 0.0); @@ -194,7 +194,7 @@ namespace OpenMS defaults_.addTag("precursor_isotope_deviation", "advanced"); defaults_.setValue("purity_interpolation", "true", "If set to true the algorithm will try to compute the purity as a time weighted linear combination of the precursor scan and the following scan. If set to false, only the precursor scan will be used."); - defaults_.setValidStrings("purity_interpolation", ListUtils::create("true,false")); + defaults_.setValidStrings("purity_interpolation", {"true","false"}); defaults_.addTag("purity_interpolation", "advanced"); defaultsToParam_(); @@ -202,7 +202,7 @@ namespace OpenMS void IsobaricChannelExtractor::updateMembers_() { - selected_activation_ = getParameters().getValue("select_activation"); + selected_activation_ = getParameters().getValue("select_activation").toString(); reporter_mass_shift_ = getParameters().getValue("reporter_mass_shift"); min_precursor_intensity_ = getParameters().getValue("min_precursor_intensity"); keep_unannotated_precursor_ = getParameters().getValue("keep_unannotated_precursor") == "true"; diff --git a/src/openms/source/ANALYSIS/QUANTITATION/IsobaricQuantifier.cpp b/src/openms/source/ANALYSIS/QUANTITATION/IsobaricQuantifier.cpp index 17f527f6f7e..86fd73f89d9 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/IsobaricQuantifier.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/IsobaricQuantifier.cpp @@ -71,12 +71,12 @@ namespace OpenMS defaults_.setValue("isotope_correction", "true", "Enable isotope correction (highly recommended). " "Note that you need to provide a correct isotope correction matrix " "otherwise the tool will fail or produce invalid results."); - defaults_.setValidStrings("isotope_correction", ListUtils::create("true,false")); + defaults_.setValidStrings("isotope_correction", {"true","false"}); defaults_.setValue("normalization", "false", "Enable normalization of channel intensities with respect to the reference channel. " "The normalization is done by using the Median of Ratios (every channel / Reference). " "Also the ratio of medians (from any channel and reference) is provided as control measure!"); - defaults_.setValidStrings("normalization", ListUtils::create("true,false")); + defaults_.setValidStrings("normalization", {"true","false"}); defaultsToParam_(); } diff --git a/src/openms/source/ANALYSIS/QUANTITATION/IsobaricQuantitationMethod.cpp b/src/openms/source/ANALYSIS/QUANTITATION/IsobaricQuantitationMethod.cpp index 14568af940f..05dac439e8f 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/IsobaricQuantitationMethod.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/IsobaricQuantitationMethod.cpp @@ -35,6 +35,7 @@ #include #include +#include namespace OpenMS { diff --git a/src/openms/source/ANALYSIS/QUANTITATION/ItraqEightPlexQuantitationMethod.cpp b/src/openms/source/ANALYSIS/QUANTITATION/ItraqEightPlexQuantitationMethod.cpp index 9632a102e7a..5b380f6b6de 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/ItraqEightPlexQuantitationMethod.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/ItraqEightPlexQuantitationMethod.cpp @@ -35,6 +35,7 @@ #include #include +#include #include namespace OpenMS @@ -109,14 +110,14 @@ namespace OpenMS // {0.09, 4.71, 1.88, 0.00}, // {0.14, 5.66, 0.87, 0.00}, // {0.27, 7.44, 0.18, 0.00} //121 - defaults_.setValue("correction_matrix", ListUtils::create("0.00/0.00/6.89/0.22," //113 - "0.00/0.94/5.90/0.16," - "0.00/1.88/4.90/0.10," - "0.00/2.82/3.90/0.07," - "0.06/3.77/2.99/0.00," - "0.09/4.71/1.88/0.00," - "0.14/5.66/0.87/0.00," - "0.27/7.44/0.18/0.00"), //121 + defaults_.setValue("correction_matrix", std::vector{"0.00/0.00/6.89/0.22", //113 + "0.00/0.94/5.90/0.16", + "0.00/1.88/4.90/0.10", + "0.00/2.82/3.90/0.07", + "0.06/3.77/2.99/0.00", + "0.09/4.71/1.88/0.00", + "0.14/5.66/0.87/0.00", + "0.27/7.44/0.18/0.00"}, //121 "Correction matrix for isotope distributions (see documentation); use the following format: <-2Da>/<-1Da>/<+1Da>/<+2Da>; e.g. '0/0.3/4/0', '0.1/0.3/3/0.2'"); defaultsToParam_(); @@ -124,14 +125,14 @@ namespace OpenMS void ItraqEightPlexQuantitationMethod::updateMembers_() { - channels_[0].description = param_.getValue("channel_113_description"); - channels_[1].description = param_.getValue("channel_114_description"); - channels_[2].description = param_.getValue("channel_115_description"); - channels_[3].description = param_.getValue("channel_116_description"); - channels_[4].description = param_.getValue("channel_117_description"); - channels_[5].description = param_.getValue("channel_118_description"); - channels_[6].description = param_.getValue("channel_119_description"); - channels_[7].description = param_.getValue("channel_121_description"); + channels_[0].description = param_.getValue("channel_113_description").toString(); + channels_[1].description = param_.getValue("channel_114_description").toString(); + channels_[2].description = param_.getValue("channel_115_description").toString(); + channels_[3].description = param_.getValue("channel_116_description").toString(); + channels_[4].description = param_.getValue("channel_117_description").toString(); + channels_[5].description = param_.getValue("channel_118_description").toString(); + channels_[6].description = param_.getValue("channel_119_description").toString(); + channels_[7].description = param_.getValue("channel_121_description").toString(); // compute the index of the reference channel Int ref_ch = param_.getValue("reference_channel"); @@ -166,7 +167,7 @@ namespace OpenMS Matrix ItraqEightPlexQuantitationMethod::getIsotopeCorrectionMatrix() const { - StringList iso_correction = getParameters().getValue("correction_matrix"); + StringList iso_correction = ListUtils::toStringList(getParameters().getValue("correction_matrix")); return stringListToIsotopCorrectionMatrix_(iso_correction); } diff --git a/src/openms/source/ANALYSIS/QUANTITATION/ItraqFourPlexQuantitationMethod.cpp b/src/openms/source/ANALYSIS/QUANTITATION/ItraqFourPlexQuantitationMethod.cpp index 17ed77eed01..7b6aa7b0980 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/ItraqFourPlexQuantitationMethod.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/ItraqFourPlexQuantitationMethod.cpp @@ -35,6 +35,7 @@ #include #include +#include namespace OpenMS { @@ -74,10 +75,10 @@ namespace OpenMS // {0.0, 2.0, 5.6, 0.1}, // {0.0, 3.0, 4.5, 0.1}, // {0.1, 4.0, 3.5, 0.1} //117 - defaults_.setValue("correction_matrix", ListUtils::create("0.0/1.0/5.9/0.2," - "0.0/2.0/5.6/0.1," - "0.0/3.0/4.5/0.1," - "0.1/4.0/3.5/0.1"), + defaults_.setValue("correction_matrix", std::vector{"0.0/1.0/5.9/0.2", + "0.0/2.0/5.6/0.1", + "0.0/3.0/4.5/0.1", + "0.1/4.0/3.5/0.1"}, "Correction matrix for isotope distributions (see documentation); use the following format: <-2Da>/<-1Da>/<+1Da>/<+2Da>; e.g. '0/0.3/4/0', '0.1/0.3/3/0.2'"); defaultsToParam_(); @@ -85,10 +86,10 @@ namespace OpenMS void ItraqFourPlexQuantitationMethod::updateMembers_() { - channels_[0].description = param_.getValue("channel_114_description"); - channels_[1].description = param_.getValue("channel_115_description"); - channels_[2].description = param_.getValue("channel_116_description"); - channels_[3].description = param_.getValue("channel_117_description"); + channels_[0].description = param_.getValue("channel_114_description").toString(); + channels_[1].description = param_.getValue("channel_115_description").toString(); + channels_[2].description = param_.getValue("channel_116_description").toString(); + channels_[3].description = param_.getValue("channel_117_description").toString(); // compute the index of the reference channel reference_channel_ = ((Int) param_.getValue("reference_channel")) - 114; @@ -133,7 +134,7 @@ namespace OpenMS Matrix ItraqFourPlexQuantitationMethod::getIsotopeCorrectionMatrix() const { - StringList iso_correction = getParameters().getValue("correction_matrix"); + StringList iso_correction = ListUtils::toStringList(getParameters().getValue("correction_matrix")); return stringListToIsotopCorrectionMatrix_(iso_correction); } diff --git a/src/openms/source/ANALYSIS/QUANTITATION/PeptideAndProteinQuant.cpp b/src/openms/source/ANALYSIS/QUANTITATION/PeptideAndProteinQuant.cpp index 0fce2e5362b..5a1845af2d0 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/PeptideAndProteinQuant.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/PeptideAndProteinQuant.cpp @@ -49,9 +49,9 @@ namespace OpenMS defaults_.setMinInt("top", 0); defaults_.setValue("average", "median", "Averaging method used to compute protein abundances from peptide abundances"); - defaults_.setValidStrings("average", ListUtils::create("median,mean,weighted_mean,sum")); + defaults_.setValidStrings("average", {"median","mean","weighted_mean","sum"}); - StringList true_false = ListUtils::create("true,false"); + std::vector true_false = {"true","false"}; defaults_.setValue("include_all", "false", "Include results for proteins with fewer proteotypic peptides than indicated by 'top' (no effect if 'top' is 0 or 1)"); defaults_.setValidStrings("include_all", true_false); @@ -414,7 +414,7 @@ namespace OpenMS } Size top = param_.getValue("top"); - String average = param_.getValue("average"); + std::string average = param_.getValue("average"); bool include_all = param_.getValue("include_all") == "true"; bool fix_peptides = param_.getValue("consensus:fix_peptides") == "true"; diff --git a/src/openms/source/ANALYSIS/QUANTITATION/ProteinResolver.cpp b/src/openms/source/ANALYSIS/QUANTITATION/ProteinResolver.cpp index b5c6b127cf4..417dd138bfb 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/ProteinResolver.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/ProteinResolver.cpp @@ -57,7 +57,7 @@ namespace OpenMS defaults_.setValue("resolver:min_length", 6, "Minimum length of peptide"); defaults_.setMinInt("resolver:min_length", 1); defaults_.setValue("resolver:enzyme", "Trypsin", "Digestion enzyme"); - defaults_.setValidStrings("resolver:enzyme", ListUtils::create("Trypsin")); + defaults_.setValidStrings("resolver:enzyme", {"Trypsin"}); defaults_.setSectionDescription("resolver", "Additional options for algorithm"); @@ -444,7 +444,7 @@ namespace OpenMS vector & isd_groups) { ProteaseDigestion digestor; - String enzyme_name = param_.getValue("resolver:enzyme"); + String enzyme_name = param_.getValue("resolver:enzyme").toString(); digestor.setEnzyme(enzyme_name); UInt min_size = param_.getValue("resolver:min_length"); UInt missed_cleavages = param_.getValue("resolver:missed_cleavages"); diff --git a/src/openms/source/ANALYSIS/QUANTITATION/QuantitativeExperimentalDesign.cpp b/src/openms/source/ANALYSIS/QUANTITATION/QuantitativeExperimentalDesign.cpp index 47133d6544d..a047f0e96df 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/QuantitativeExperimentalDesign.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/QuantitativeExperimentalDesign.cpp @@ -58,7 +58,7 @@ namespace OpenMS defaults_.setValue("designer:file", "File", "Identifier for the file name."); defaults_.setValue("designer:separator", "tab", "Separator, which should be used to split a row into columns"); - defaults_.setValidStrings("designer:separator", ListUtils::create("tab,semi-colon,comma,whitespace")); + defaults_.setValidStrings("designer:separator", {"tab","semi-colon","comma","whitespace"}); defaults_.setSectionDescription("designer", "Additional options for quantitative experimental design"); @@ -227,8 +227,8 @@ namespace OpenMS void QuantitativeExperimentalDesign::analyzeHeader_(UInt& expCol, UInt& fileCol, StringList& header) { // read parameter - String experiment = param_.getValue("designer:experiment"); - String fileName = param_.getValue("designer:file"); + std::string experiment = param_.getValue("designer:experiment"); + std::string fileName = param_.getValue("designer:file"); // iterate through header strings to look for matching identifier UInt col = 0; @@ -259,7 +259,7 @@ namespace OpenMS void QuantitativeExperimentalDesign::getSeparator_(String& separator) { // get separator from parameter setting - String sep = param_.getValue("designer:separator"); + std::string sep = param_.getValue("designer:separator"); // assign if (sep.compare("tab") == 0) diff --git a/src/openms/source/ANALYSIS/QUANTITATION/TMTElevenPlexQuantitationMethod.cpp b/src/openms/source/ANALYSIS/QUANTITATION/TMTElevenPlexQuantitationMethod.cpp index aec6b721202..f0825ee254e 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/TMTElevenPlexQuantitationMethod.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/TMTElevenPlexQuantitationMethod.cpp @@ -42,7 +42,7 @@ namespace OpenMS { const String TMTElevenPlexQuantitationMethod::name_ = "tmt11plex"; -const std::vector TMTElevenPlexQuantitationMethod::channel_names_ = {"126","127N","127C","128N","128C","129N","129C","130N","130C","131N","131C"}; +const std::vector TMTElevenPlexQuantitationMethod::channel_names_ = {"126","127N","127C","128N","128C","129N","129C","130N","130C","131N","131C"}; TMTElevenPlexQuantitationMethod::TMTElevenPlexQuantitationMethod() { @@ -101,17 +101,17 @@ void TMTElevenPlexQuantitationMethod::setDefaultParams_() defaults_.setValue("reference_channel", "126", "The reference channel (126, 127N, 127C, 128N, 128C, 129N, 129C, 130N, 130C, 131N, 131C)."); defaults_.setValidStrings("reference_channel", TMTElevenPlexQuantitationMethod::channel_names_); - defaults_.setValue("correction_matrix", ListUtils::create("0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0"), + defaults_.setValue("correction_matrix", std::vector{"0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0"}, "Correction matrix for isotope distributions (see documentation); use the following format: <-2Da>/<-1Da>/<+1Da>/<+2Da>; e.g. '0/0.3/4/0', '0.1/0.3/3/0.2'"); defaultsToParam_(); @@ -119,22 +119,22 @@ void TMTElevenPlexQuantitationMethod::setDefaultParams_() void TMTElevenPlexQuantitationMethod::updateMembers_() { - channels_[0].description = param_.getValue("channel_126_description"); - channels_[1].description = param_.getValue("channel_127N_description"); - channels_[2].description = param_.getValue("channel_127C_description"); - channels_[3].description = param_.getValue("channel_128N_description"); - channels_[4].description = param_.getValue("channel_128C_description"); - channels_[5].description = param_.getValue("channel_129N_description"); - channels_[6].description = param_.getValue("channel_129C_description"); - channels_[7].description = param_.getValue("channel_130N_description"); - channels_[8].description = param_.getValue("channel_130C_description"); - channels_[9].description = param_.getValue("channel_131N_description"); - channels_[10].description = param_.getValue("channel_131C_description"); + channels_[0].description = param_.getValue("channel_126_description").toString(); + channels_[1].description = param_.getValue("channel_127N_description").toString(); + channels_[2].description = param_.getValue("channel_127C_description").toString(); + channels_[3].description = param_.getValue("channel_128N_description").toString(); + channels_[4].description = param_.getValue("channel_128C_description").toString(); + channels_[5].description = param_.getValue("channel_129N_description").toString(); + channels_[6].description = param_.getValue("channel_129C_description").toString(); + channels_[7].description = param_.getValue("channel_130N_description").toString(); + channels_[8].description = param_.getValue("channel_130C_description").toString(); + channels_[9].description = param_.getValue("channel_131N_description").toString(); + channels_[10].description = param_.getValue("channel_131C_description").toString(); // compute the index of the reference channel - std::vector::const_iterator t_it = std::find(TMTElevenPlexQuantitationMethod::channel_names_.begin(), + std::vector::const_iterator t_it = std::find(TMTElevenPlexQuantitationMethod::channel_names_.begin(), TMTElevenPlexQuantitationMethod::channel_names_.end(), - (String) param_.getValue("reference_channel")); + param_.getValue("reference_channel")); reference_channel_ = t_it - TMTElevenPlexQuantitationMethod::channel_names_.begin(); } @@ -179,7 +179,7 @@ Size TMTElevenPlexQuantitationMethod::getNumberOfChannels() const Matrix TMTElevenPlexQuantitationMethod::getIsotopeCorrectionMatrix() const { - StringList iso_correction = getParameters().getValue("correction_matrix"); + StringList iso_correction = ListUtils::toStringList(getParameters().getValue("correction_matrix")); return stringListToIsotopCorrectionMatrix_(iso_correction); } diff --git a/src/openms/source/ANALYSIS/QUANTITATION/TMTSixPlexQuantitationMethod.cpp b/src/openms/source/ANALYSIS/QUANTITATION/TMTSixPlexQuantitationMethod.cpp index a62b35ad0c4..469b1f9ce5d 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/TMTSixPlexQuantitationMethod.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/TMTSixPlexQuantitationMethod.cpp @@ -35,6 +35,7 @@ #include #include +#include namespace OpenMS { @@ -74,12 +75,12 @@ namespace OpenMS // {0.0, 2.0, 5.6, 0.1}, // {0.0, 3.0, 4.5, 0.1}, // {0.1, 4.0, 3.5, 0.1} //117 - defaults_.setValue("correction_matrix", ListUtils::create("0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0," - "0.0/0.0/0.0/0.0"), + defaults_.setValue("correction_matrix", std::vector{"0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0", + "0.0/0.0/0.0/0.0"}, "Correction matrix for isotope distributions (see documentation); use the following format: <-2Da>/<-1Da>/<+1Da>/<+2Da>; e.g. '0/0.3/4/0', '0.1/0.3/3/0.2'"); defaultsToParam_(); @@ -87,12 +88,12 @@ namespace OpenMS void TMTSixPlexQuantitationMethod::updateMembers_() { - channels_[0].description = param_.getValue("channel_126_description"); - channels_[1].description = param_.getValue("channel_127_description"); - channels_[2].description = param_.getValue("channel_128_description"); - channels_[3].description = param_.getValue("channel_129_description"); - channels_[4].description = param_.getValue("channel_130_description"); - channels_[5].description = param_.getValue("channel_131_description"); + channels_[0].description = param_.getValue("channel_126_description").toString(); + channels_[1].description = param_.getValue("channel_127_description").toString(); + channels_[2].description = param_.getValue("channel_128_description").toString(); + channels_[3].description = param_.getValue("channel_129_description").toString(); + channels_[4].description = param_.getValue("channel_130_description").toString(); + channels_[5].description = param_.getValue("channel_131_description").toString(); // compute the index of the reference channel reference_channel_ = ((Int) param_.getValue("reference_channel")) - 126; @@ -137,7 +138,7 @@ namespace OpenMS Matrix TMTSixPlexQuantitationMethod::getIsotopeCorrectionMatrix() const { - StringList iso_correction = getParameters().getValue("correction_matrix"); + StringList iso_correction = ListUtils::toStringList(getParameters().getValue("correction_matrix")); return stringListToIsotopCorrectionMatrix_(iso_correction); } diff --git a/src/openms/source/ANALYSIS/QUANTITATION/TMTSixteenPlexQuantitationMethod.cpp b/src/openms/source/ANALYSIS/QUANTITATION/TMTSixteenPlexQuantitationMethod.cpp index c25995c5ce7..8a76237e801 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/TMTSixteenPlexQuantitationMethod.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/TMTSixteenPlexQuantitationMethod.cpp @@ -44,7 +44,7 @@ namespace OpenMS { const String TMTSixteenPlexQuantitationMethod::name_ = "tmt16plex"; -const std::vector TMTSixteenPlexQuantitationMethod::channel_names_ = {"126","127N","127C","128N","128C","129N","129C","130N","130C","131N","131C","132N","132C","133N","133C","134N"}; +const std::vector TMTSixteenPlexQuantitationMethod::channel_names_ = {"126","127N","127C","128N","128C","129N","129C","130N","130C","131N","131C","132N","132C","133N","133C","134N"}; TMTSixteenPlexQuantitationMethod::TMTSixteenPlexQuantitationMethod() { @@ -113,22 +113,22 @@ void TMTSixteenPlexQuantitationMethod::setDefaultParams_() defaults_.setValue("reference_channel", "126", "The reference channel (126, 127N, 127C, 128N, 128C, 129N, 129C, 130N, 130C, 131N, 131C)."); defaults_.setValidStrings("reference_channel", TMTSixteenPlexQuantitationMethod::channel_names_); - defaults_.setValue("correction_matrix", ListUtils::create("0.0/0.0/8.02/0.0," - "0.0/0.68/7.46/0.0," - "0.0/0.71/6.94/0.0," - "0.0/1.88/6.67/0.0," - "0.0/1.34/5.59/0.0," - "0.0/2.41/5.48/0.0," - "0.0/2.34/5.19/0.0," - "0.0/3.53/4.57/0.0," - "0.0/2.67/4.16/0.0," - "0.0/3.92/3.73/0.0," - "0.0/3.69/3.14/0.0," - "0.0/3.22/2.76/0.0," - "0.0/4.11/2.0/0.0," - "0.0/3.85/1.58/0.0," - "0.0/4.63/1.18/0.0," - "0.0/5.22/0.86/0.0"), + defaults_.setValue("correction_matrix", std::vector{"0.0/0.0/8.02/0.0", + "0.0/0.68/7.46/0.0", + "0.0/0.71/6.94/0.0", + "0.0/1.88/6.67/0.0", + "0.0/1.34/5.59/0.0", + "0.0/2.41/5.48/0.0", + "0.0/2.34/5.19/0.0", + "0.0/3.53/4.57/0.0", + "0.0/2.67/4.16/0.0", + "0.0/3.92/3.73/0.0", + "0.0/3.69/3.14/0.0", + "0.0/3.22/2.76/0.0", + "0.0/4.11/2.0/0.0", + "0.0/3.85/1.58/0.0", + "0.0/4.63/1.18/0.0", + "0.0/5.22/0.86/0.0"}, "Correction matrix for isotope distributions (see documentation); use the following format: <-2Da>/<-1Da>/<+1Da>/<+2Da>; e.g. '0/0.3/4/0', '0.1/0.3/3/0.2'"); defaultsToParam_(); @@ -136,28 +136,28 @@ void TMTSixteenPlexQuantitationMethod::setDefaultParams_() void TMTSixteenPlexQuantitationMethod::updateMembers_() { - channels_[0].description = param_.getValue("channel_126_description"); - channels_[1].description = param_.getValue("channel_127N_description"); - channels_[2].description = param_.getValue("channel_127C_description"); - channels_[3].description = param_.getValue("channel_128N_description"); - channels_[4].description = param_.getValue("channel_128C_description"); - channels_[5].description = param_.getValue("channel_129N_description"); - channels_[6].description = param_.getValue("channel_129C_description"); - channels_[7].description = param_.getValue("channel_130N_description"); - channels_[8].description = param_.getValue("channel_130C_description"); - channels_[9].description = param_.getValue("channel_131N_description"); - channels_[10].description = param_.getValue("channel_131C_description"); - channels_[11].description = param_.getValue("channel_132N_description"); - channels_[12].description = param_.getValue("channel_132C_description"); - channels_[13].description = param_.getValue("channel_133N_description"); - channels_[14].description = param_.getValue("channel_133C_description"); - channels_[15].description = param_.getValue("channel_134N_description"); + channels_[0].description = param_.getValue("channel_126_description").toString(); + channels_[1].description = param_.getValue("channel_127N_description").toString(); + channels_[2].description = param_.getValue("channel_127C_description").toString(); + channels_[3].description = param_.getValue("channel_128N_description").toString(); + channels_[4].description = param_.getValue("channel_128C_description").toString(); + channels_[5].description = param_.getValue("channel_129N_description").toString(); + channels_[6].description = param_.getValue("channel_129C_description").toString(); + channels_[7].description = param_.getValue("channel_130N_description").toString(); + channels_[8].description = param_.getValue("channel_130C_description").toString(); + channels_[9].description = param_.getValue("channel_131N_description").toString(); + channels_[10].description = param_.getValue("channel_131C_description").toString(); + channels_[11].description = param_.getValue("channel_132N_description").toString(); + channels_[12].description = param_.getValue("channel_132C_description").toString(); + channels_[13].description = param_.getValue("channel_133N_description").toString(); + channels_[14].description = param_.getValue("channel_133C_description").toString(); + channels_[15].description = param_.getValue("channel_134N_description").toString(); // compute the index of the reference channel - std::vector::const_iterator t_it = std::find(TMTSixteenPlexQuantitationMethod::channel_names_.begin(), + std::vector::const_iterator t_it = std::find(TMTSixteenPlexQuantitationMethod::channel_names_.begin(), TMTSixteenPlexQuantitationMethod::channel_names_.end(), - (String) param_.getValue("reference_channel")); + param_.getValue("reference_channel")); reference_channel_ = t_it - TMTSixteenPlexQuantitationMethod::channel_names_.begin(); } @@ -202,7 +202,7 @@ Size TMTSixteenPlexQuantitationMethod::getNumberOfChannels() const Matrix TMTSixteenPlexQuantitationMethod::getIsotopeCorrectionMatrix() const { - StringList iso_correction = getParameters().getValue("correction_matrix"); + StringList iso_correction = ListUtils::toStringList(getParameters().getValue("correction_matrix")); return stringListToIsotopCorrectionMatrix_(iso_correction); } diff --git a/src/openms/source/ANALYSIS/QUANTITATION/TMTTenPlexQuantitationMethod.cpp b/src/openms/source/ANALYSIS/QUANTITATION/TMTTenPlexQuantitationMethod.cpp index 9c30d643344..7cac7b8e14a 100644 --- a/src/openms/source/ANALYSIS/QUANTITATION/TMTTenPlexQuantitationMethod.cpp +++ b/src/openms/source/ANALYSIS/QUANTITATION/TMTTenPlexQuantitationMethod.cpp @@ -35,11 +35,12 @@ #include #include +#include namespace OpenMS { const String TMTTenPlexQuantitationMethod::name_ = "tmt10plex"; -const std::vector TMTTenPlexQuantitationMethod::channel_names_ = {"126","127N","127C","128N","128C","129N","129C","130N","130C","131"}; +const std::vector TMTTenPlexQuantitationMethod::channel_names_ = {"126","127N","127C","128N","128C","129N","129C","130N","130C","131"}; TMTTenPlexQuantitationMethod::TMTTenPlexQuantitationMethod() { @@ -91,16 +92,16 @@ void TMTTenPlexQuantitationMethod::setDefaultParams_() defaults_.setValue("reference_channel", "126", "The reference channel (126, 127N, 127C, 128N, 128C, 129N, 129C, 130N, 130C, 131)."); defaults_.setValidStrings("reference_channel", TMTTenPlexQuantitationMethod::channel_names_); - defaults_.setValue("correction_matrix", ListUtils::create("0.0/0.0/5.09/0.0," - "0.0/0.25/5.27/0.0," - "0.0/0.37/5.36/0.15," - "0.0/0.65/4.17/0.1," - "0.08/0.49/3.06/0.0," - "0.01/0.71/3.07/0.0," - "0.0/1.32/2.62/0.0," - "0.02/1.28/2.75/2.53," - "0.03/2.08/2.23/0.0," - "0.08/1.99/1.65/0.0"), + defaults_.setValue("correction_matrix", std::vector{"0.0/0.0/5.09/0.0", + "0.0/0.25/5.27/0.0", + "0.0/0.37/5.36/0.15", + "0.0/0.65/4.17/0.1", + "0.08/0.49/3.06/0.0", + "0.01/0.71/3.07/0.0", + "0.0/1.32/2.62/0.0", + "0.02/1.28/2.75/2.53", + "0.03/2.08/2.23/0.0", + "0.08/1.99/1.65/0.0"}, "Correction matrix for isotope distributions (see documentation); use the following format: <-2Da>/<-1Da>/<+1Da>/<+2Da>; e.g. '0/0.3/4/0', '0.1/0.3/3/0.2'"); defaultsToParam_(); @@ -108,21 +109,21 @@ void TMTTenPlexQuantitationMethod::setDefaultParams_() void TMTTenPlexQuantitationMethod::updateMembers_() { - channels_[0].description = param_.getValue("channel_126_description"); - channels_[1].description = param_.getValue("channel_127N_description"); - channels_[2].description = param_.getValue("channel_127C_description"); - channels_[3].description = param_.getValue("channel_128N_description"); - channels_[4].description = param_.getValue("channel_128C_description"); - channels_[5].description = param_.getValue("channel_129N_description"); - channels_[6].description = param_.getValue("channel_129C_description"); - channels_[7].description = param_.getValue("channel_130N_description"); - channels_[8].description = param_.getValue("channel_130C_description"); - channels_[9].description = param_.getValue("channel_131_description"); + channels_[0].description = param_.getValue("channel_126_description").toString(); + channels_[1].description = param_.getValue("channel_127N_description").toString(); + channels_[2].description = param_.getValue("channel_127C_description").toString(); + channels_[3].description = param_.getValue("channel_128N_description").toString(); + channels_[4].description = param_.getValue("channel_128C_description").toString(); + channels_[5].description = param_.getValue("channel_129N_description").toString(); + channels_[6].description = param_.getValue("channel_129C_description").toString(); + channels_[7].description = param_.getValue("channel_130N_description").toString(); + channels_[8].description = param_.getValue("channel_130C_description").toString(); + channels_[9].description = param_.getValue("channel_131_description").toString(); // compute the index of the reference channel - std::vector::const_iterator t_it = std::find(TMTTenPlexQuantitationMethod::channel_names_.begin(), + std::vector::const_iterator t_it = std::find(TMTTenPlexQuantitationMethod::channel_names_.begin(), TMTTenPlexQuantitationMethod::channel_names_.end(), - (String) param_.getValue("reference_channel")); + param_.getValue("reference_channel")); reference_channel_ = t_it - TMTTenPlexQuantitationMethod::channel_names_.begin(); } @@ -166,7 +167,7 @@ Size TMTTenPlexQuantitationMethod::getNumberOfChannels() const Matrix TMTTenPlexQuantitationMethod::getIsotopeCorrectionMatrix() const { - StringList iso_correction = getParameters().getValue("correction_matrix"); + StringList iso_correction = ListUtils::toStringList(getParameters().getValue("correction_matrix")); return stringListToIsotopCorrectionMatrix_(iso_correction); } diff --git a/src/openms/source/ANALYSIS/SVM/SimpleSVM.cpp b/src/openms/source/ANALYSIS/SVM/SimpleSVM.cpp index a3544bab194..fe736187628 100644 --- a/src/openms/source/ANALYSIS/SVM/SimpleSVM.cpp +++ b/src/openms/source/ANALYSIS/SVM/SimpleSVM.cpp @@ -36,6 +36,7 @@ #include #include #include +#include using namespace OpenMS; using namespace std; @@ -45,7 +46,7 @@ SimpleSVM::SimpleSVM(): DefaultParamHandler("SimpleSVM"), data_(), model_(nullptr) { defaults_.setValue("kernel", "RBF", "SVM kernel"); - defaults_.setValidStrings("kernel", ListUtils::create("RBF,linear")); + defaults_.setValidStrings("kernel", {"RBF","linear"}); defaults_.setValue("xval", 5, "Number of partitions for cross-validation (parameter optimization)"); defaults_.setMinInt("xval", 1); @@ -56,7 +57,7 @@ SimpleSVM::SimpleSVM(): values = "-15,-13,-11,-9,-7,-5,-3,-1,1,3"; defaults_.setValue("log2_gamma", ListUtils::create(values), "Values to try for the SVM parameter 'gamma' during parameter optimization (RBF kernel only). A value 'x' is used as 'gamma = 2^x'."); - vector advanced(1, "advanced"); + vector advanced(1, "advanced"); defaults_.setValue("epsilon", 0.001, "Stopping criterion", advanced); defaults_.setMinFloat("epsilon", 0.0); @@ -67,7 +68,7 @@ SimpleSVM::SimpleSVM(): defaults_.setValue("no_shrinking", "false", "Disable the shrinking heuristics", advanced); defaults_.setValidStrings("no_shrinking", - ListUtils::create("true,false")); + {"true","false"}); defaultsToParam_(); @@ -138,7 +139,7 @@ void SimpleSVM::setup(PredictorMap& predictors, const map& labels) OPENMS_LOG_INFO << msg << endl; svm_params_.svm_type = C_SVC; - String kernel = param_.getValue("kernel"); + std::string kernel = param_.getValue("kernel"); svm_params_.kernel_type = (kernel == "RBF") ? RBF : LINEAR; svm_params_.eps = param_.getValue("epsilon"); svm_params_.cache_size = param_.getValue("cache_size"); diff --git a/src/openms/source/ANALYSIS/TARGETED/InclusionExclusionList.cpp b/src/openms/source/ANALYSIS/TARGETED/InclusionExclusionList.cpp index 3a14ba130ff..30ab9c46f31 100644 --- a/src/openms/source/ANALYSIS/TARGETED/InclusionExclusionList.cpp +++ b/src/openms/source/ANALYSIS/TARGETED/InclusionExclusionList.cpp @@ -52,9 +52,9 @@ namespace OpenMS defaults_.setValue("missed_cleavages", 0, "Number of missed cleavages used for protein digestion.\n"); defaults_.setValue("RT:unit", "minutes", "Create lists with units as seconds instead of minutes"); - defaults_.setValidStrings("RT:unit", ListUtils::create("minutes,seconds")); + defaults_.setValidStrings("RT:unit", {"minutes","seconds"}); defaults_.setValue("RT:use_relative", "true", "Use relative RT window, which depends on RT of precursor."); - defaults_.setValidStrings("RT:use_relative", ListUtils::create("true,false")); + defaults_.setValidStrings("RT:use_relative", {"true","false"}); defaults_.setValue("RT:window_relative", 0.05, "[for RT:use_relative == true] The relative factor X for the RT exclusion window, e.g. the window is calculated as [rt - rt*X, rt + rt*X]."); defaults_.setMinFloat("RT:window_relative", 0.0); defaults_.setMaxFloat("RT:window_relative", 10.0); @@ -63,7 +63,7 @@ namespace OpenMS defaults_.setValue("merge:mz_tol", 10.0, "Two inclusion/exclusion windows are merged when they (almost) overlap in RT (see 'rt_tol') and are close in m/z by this tolerance. Unit of this is defined in 'mz_tol_unit'."); defaults_.setMinFloat("merge:mz_tol", 0.0); defaults_.setValue("merge:mz_tol_unit", "ppm", "Unit of 'mz_tol'"); - defaults_.setValidStrings("merge:mz_tol_unit", ListUtils::create("ppm,Da")); + defaults_.setValidStrings("merge:mz_tol_unit", {"ppm","Da"}); defaults_.setValue("merge:rt_tol", 1.1, "Maximal RT delta (in seconds) which would allow two windows in RT to overlap (which causes merging the windows). Two inclusion/exclusion windows are merged when they (almost) overlap in RT and are close in m/z by this tolerance (see 'mz_tol'). Unit of this param is [seconds]."); defaults_.setMinFloat("merge:rt_tol", 0.0); diff --git a/src/openms/source/ANALYSIS/TARGETED/MRMMapping.cpp b/src/openms/source/ANALYSIS/TARGETED/MRMMapping.cpp index 50c3e616bbe..3bb952d09ae 100644 --- a/src/openms/source/ANALYSIS/TARGETED/MRMMapping.cpp +++ b/src/openms/source/ANALYSIS/TARGETED/MRMMapping.cpp @@ -50,10 +50,10 @@ namespace OpenMS defaults_.setValue("product_tolerance", 0.1, "Product tolerance when mapping (in Th)"); defaults_.setValue("map_multiple_assays", "false", "Allow to map multiple assays to chromatograms and duplicate these chromatograms in the output."); - defaults_.setValidStrings("map_multiple_assays", ListUtils::create("true,false")); + defaults_.setValidStrings("map_multiple_assays", {"true","false"}); defaults_.setValue("error_on_unmapped", "false", "Treat remaining, unmapped chromatograms as an error"); - defaults_.setValidStrings("error_on_unmapped", ListUtils::create("true,false")); + defaults_.setValidStrings("error_on_unmapped", {"true","false"}); // write defaults into Param object param_ defaultsToParam_(); diff --git a/src/openms/source/ANALYSIS/TARGETED/MetaboTargetedTargetDecoy.cpp b/src/openms/source/ANALYSIS/TARGETED/MetaboTargetedTargetDecoy.cpp index 632fc6919d0..2535aa84aad 100644 --- a/src/openms/source/ANALYSIS/TARGETED/MetaboTargetedTargetDecoy.cpp +++ b/src/openms/source/ANALYSIS/TARGETED/MetaboTargetedTargetDecoy.cpp @@ -175,7 +175,7 @@ namespace OpenMS if (it.decoy_compound_ref.empty()) { // add a potential decoy with the new decoy masses to the mapping - it.decoy_compound_ref = std::regex_replace(it.target_compound_ref, std::regex("_\\["), "_decoy_["); + it.decoy_compound_ref = std::regex_replace(it.target_compound_ref, std::regex(R"(_\[)"), "_decoy_["); std::transform(it.target_product_masses.begin(), it.target_product_masses.end(), std::back_inserter(it.decoy_product_masses), @@ -245,7 +245,7 @@ namespace OpenMS { potential_decoy_transitions[i] .setNativeID(std::regex_replace(potential_decoy_transitions[i].getNativeID(), - std::regex("_\\["), + std::regex(R"(_\[)"), "_decoy_[")); potential_decoy_transitions[i] .setDecoyTransitionType(ReactionMonitoringTransition::DecoyTransitionType::DECOY); diff --git a/src/openms/source/ANALYSIS/TARGETED/OfflinePrecursorIonSelection.cpp b/src/openms/source/ANALYSIS/TARGETED/OfflinePrecursorIonSelection.cpp index 88fb754ca59..1872394f635 100644 --- a/src/openms/source/ANALYSIS/TARGETED/OfflinePrecursorIonSelection.cpp +++ b/src/openms/source/ANALYSIS/TARGETED/OfflinePrecursorIonSelection.cpp @@ -51,10 +51,10 @@ namespace OpenMS defaults_.setMinFloat("mz_isolation_window", 0.); defaults_.setValue("exclude_overlapping_peaks", "false", "If true, overlapping or nearby peaks (within 'min_mz_peak_distance') are excluded for selection."); - defaults_.setValidStrings("exclude_overlapping_peaks", ListUtils::create("true,false")); + defaults_.setValidStrings("exclude_overlapping_peaks", {"true","false"}); defaults_.setValue("Exclusion:use_dynamic_exclusion", "false", "If true dynamic exclusion is applied."); - defaults_.setValidStrings("Exclusion:use_dynamic_exclusion", ListUtils::create("true,false")); + defaults_.setValidStrings("Exclusion:use_dynamic_exclusion", {"true","false"}); defaults_.setValue("Exclusion:exclusion_time", 100., "The time (in seconds) a feature is excluded."); defaults_.setMinFloat("Exclusion:exclusion_time", 0.); diff --git a/src/openms/source/ANALYSIS/TARGETED/PSLPFormulation.cpp b/src/openms/source/ANALYSIS/TARGETED/PSLPFormulation.cpp index 67dd543dc9f..f464113c23f 100644 --- a/src/openms/source/ANALYSIS/TARGETED/PSLPFormulation.cpp +++ b/src/openms/source/ANALYSIS/TARGETED/PSLPFormulation.cpp @@ -88,7 +88,7 @@ namespace OpenMS defaults_.setValue("thresholds:use_peptide_rule", "false", "Use peptide rule instead of minimal protein id probability"); - defaults_.setValidStrings("thresholds:use_peptide_rule", ListUtils::create("true,false")); + defaults_.setValidStrings("thresholds:use_peptide_rule", {"true","false"}); defaults_.setValue("thresholds:min_peptide_ids", 2, "If use_peptide_rule is true, this parameter sets the minimal number of peptide ids for a protein id"); defaults_.setMinInt("thresholds:min_peptide_ids", 1); @@ -110,10 +110,10 @@ namespace OpenMS defaults_.setMinFloat("combined_ilp:k3", 0.); // defaults_.setMaxFloat("combined_ilp:k1",1.); defaults_.setValue("combined_ilp:scale_matching_probs", "true", "flag if detectability * rt_weight shall be scaled to cover all [0,1]"); - defaults_.setValidStrings("combined_ilp:scale_matching_probs", ListUtils::create("true,false")); + defaults_.setValidStrings("combined_ilp:scale_matching_probs", {"true","false"}); defaults_.setValue("feature_based:no_intensity_normalization", "false", "Flag indicating if intensities shall be scaled to be in [0,1]. This is done for each feature separately, so that the feature's maximal intensity in a spectrum is set to 1."); - defaults_.setValidStrings("feature_based:no_intensity_normalization", ListUtils::create("true,false")); + defaults_.setValidStrings("feature_based:no_intensity_normalization", {"true","false"}); defaults_.setValue("feature_based:max_number_precursors_per_feature", 1, "The maximal number of precursors per feature."); defaults_.setMinInt("feature_based:max_number_precursors_per_feature", 1); diff --git a/src/openms/source/ANALYSIS/TARGETED/PrecursorIonSelection.cpp b/src/openms/source/ANALYSIS/TARGETED/PrecursorIonSelection.cpp index 04122663f25..cc356d6bfce 100644 --- a/src/openms/source/ANALYSIS/TARGETED/PrecursorIonSelection.cpp +++ b/src/openms/source/ANALYSIS/TARGETED/PrecursorIonSelection.cpp @@ -51,7 +51,7 @@ namespace OpenMS solver_(LPWrapper::SOLVER_GLPK) { defaults_.setValue("type", "IPS", "Strategy for precursor ion selection."); - defaults_.setValidStrings("type", ListUtils::create("ILP_IPS,IPS,SPS,Upshift,Downshift,DEX")); + defaults_.setValidStrings("type", {"ILP_IPS","IPS","SPS","Upshift","Downshift","DEX"}); // defaults_.setValue("min_pep_ids",2,"Minimal number of identified peptides required for a protein identification."); // defaults_.setMinInt("min_pep_ids",1); defaults_.setValue("max_iteration", 100, "Maximal number of iterations."); @@ -63,7 +63,7 @@ namespace OpenMS defaults_.setValue("peptide_min_prob", 0.2, "Minimal peptide probability."); defaults_.setValue("sequential_spectrum_order", "false", "If true, precursors are selected sequentially with respect to their RT."); - defaults_.setValidStrings("sequential_spectrum_order", ListUtils::create("true,false")); + defaults_.setValidStrings("sequential_spectrum_order", {"true","false"}); defaults_.insert("MIPFormulation:", PSLPFormulation().getDefaults()); defaults_.remove("MIPFormulation:mz_tolerance"); @@ -1347,7 +1347,7 @@ namespace OpenMS else type_ = DEX; min_pep_ids_ = (UInt)param_.getValue("MIPFormulation:thresholds:min_peptide_ids"); - mz_tolerance_unit_ = (String)param_.getValue("Preprocessing:precursor_mass_tolerance_unit"); + mz_tolerance_unit_ = param_.getValue("Preprocessing:precursor_mass_tolerance_unit").toString(); mz_tolerance_ = (double)param_.getValue("Preprocessing:precursor_mass_tolerance"); max_iteration_ = (UInt) param_.getValue("max_iteration"); } diff --git a/src/openms/source/ANALYSIS/TARGETED/PrecursorIonSelectionPreprocessing.cpp b/src/openms/source/ANALYSIS/TARGETED/PrecursorIonSelectionPreprocessing.cpp index 1bae74f0e80..369f8342a29 100644 --- a/src/openms/source/ANALYSIS/TARGETED/PrecursorIonSelectionPreprocessing.cpp +++ b/src/openms/source/ANALYSIS/TARGETED/PrecursorIonSelectionPreprocessing.cpp @@ -65,7 +65,7 @@ namespace OpenMS defaults_.setValue("rt_settings:gauss_mean", -1.0, "mean of the gauss curve"); defaults_.setValue("rt_settings:gauss_sigma", 3., "std of the gauss curve"); defaults_.setValue("precursor_mass_tolerance_unit", "ppm", "Precursor mass tolerance unit."); - defaults_.setValidStrings("precursor_mass_tolerance_unit", ListUtils::create("ppm,Da")); + defaults_.setValidStrings("precursor_mass_tolerance_unit", {"ppm","Da"}); defaults_.setValue("preprocessed_db_path", "", "Path where the preprocessed database should be stored"); defaults_.setValue("preprocessed_db_pred_rt_path", "", "Path where the predicted rts of the preprocessed database should be stored"); defaults_.setValue("preprocessed_db_pred_dt_path", "", "Path where the predicted rts of the preprocessed database should be stored"); @@ -245,7 +245,7 @@ namespace OpenMS void PrecursorIonSelectionPreprocessing::loadPreprocessing() { // first check if preprocessed db already exists - String path = param_.getValue("preprocessed_db_path"); + String path = param_.getValue("preprocessed_db_path").toString(); // check if file exists std::ifstream test(path.c_str()); @@ -313,7 +313,7 @@ namespace OpenMS { // filter for taxonomy - if (entries[e].description.toUpper().hasSubstring(((String)param_.getValue("taxonomy")).toUpper())) + if (entries[e].description.toUpper().hasSubstring(((String)param_.getValue("taxonomy").toString()).toUpper())) { // preprocess entry identifier filterTaxonomyIdentifier_(entries[e]); @@ -612,7 +612,7 @@ namespace OpenMS } if (save) { - savePreprocessedDBWithRT_(db_path, (String)param_.getValue("preprocessed_db_path")); + savePreprocessedDBWithRT_(db_path, param_.getValue("preprocessed_db_path").toString()); } } @@ -636,7 +636,7 @@ namespace OpenMS for (UInt e = 0; e < entries.size(); ++e) { // filter for taxonomy - if (entries[e].description.toUpper().hasSubstring(((String)param_.getValue("taxonomy")).toUpper())) + if (entries[e].description.toUpper().hasSubstring(((String)param_.getValue("taxonomy").toString()).toUpper())) { // preprocess entry identifier filterTaxonomyIdentifier_(entries[e]); @@ -821,7 +821,7 @@ namespace OpenMS } if (save) { - savePreprocessedDB_(db_path, (String)param_.getValue("preprocessed_db_path")); + savePreprocessedDB_(db_path, param_.getValue("preprocessed_db_path").toString()); } } @@ -841,7 +841,7 @@ namespace OpenMS String db_name = db_path.substr(pos1, pos2 - pos1); out << db_name << "\t" << param_.getValue("precursor_mass_tolerance") << "\t" << param_.getValue("precursor_mass_tolerance_unit") - << "\t" << (String)param_.getValue("taxonomy"); + << "\t" << (std::string)param_.getValue("taxonomy"); // first save protein_masses_map out << prot_masses_.size() << std::endl; #ifdef PISP_DEBUG @@ -917,7 +917,7 @@ namespace OpenMS String db_name = db_path.substr(pos1, pos2 - pos1); out << db_name << "\t" << param_.getValue("precursor_mass_tolerance") << "\t" << param_.getValue("precursor_mass_tolerance_unit") - << "\t" << (String)param_.getValue("taxonomy"); + << "\t" << (std::string)param_.getValue("taxonomy"); // first save protein_masses_map out << prot_masses_.size() << std::endl; #ifdef PISP_DEBUG @@ -933,7 +933,7 @@ namespace OpenMS for (UInt e = 0; e < entries.size(); ++e) { // filter for taxonomy - if (entries[e].description.toUpper().hasSubstring(((String)param_.getValue("taxonomy")).toUpper())) + if (entries[e].description.toUpper().hasSubstring(((String)param_.getValue("taxonomy").toString()).toUpper())) { // preprocess entry identifier filterTaxonomyIdentifier_(entries[e]); diff --git a/src/openms/source/ANALYSIS/XLMS/OpenPepXLAlgorithm.cpp b/src/openms/source/ANALYSIS/XLMS/OpenPepXLAlgorithm.cpp index 1d19646d4d7..6f97f042adc 100644 --- a/src/openms/source/ANALYSIS/XLMS/OpenPepXLAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/XLMS/OpenPepXLAlgorithm.cpp @@ -66,12 +66,12 @@ using namespace OpenMS; : DefaultParamHandler("OpenPepXLAlgorithm") { defaults_.setValue("decoy_string", "DECOY_", "String that was appended (or prefixed - see 'prefix' flag below) to the accessions in the protein database to indicate decoy proteins."); - StringList bool_strings = ListUtils::create("true,false"); + std::vector bool_strings = {"true","false"}; defaults_.setValue("decoy_prefix", "true", "Set to true, if the decoy_string is a prefix of accessions in the protein database. Otherwise it is a suffix."); defaults_.setValidStrings("decoy_prefix", bool_strings); defaults_.setValue("precursor:mass_tolerance", 10.0, "Width of precursor mass tolerance window"); - StringList mass_tolerance_unit_valid_strings = ListUtils::create("ppm,Da"); + std::vector mass_tolerance_unit_valid_strings = {"ppm","Da"}; defaults_.setValue("precursor:mass_tolerance_unit", "ppm", "Unit of precursor mass tolerance."); defaults_.setValidStrings("precursor:mass_tolerance_unit", mass_tolerance_unit_valid_strings); defaults_.setValue("precursor:min_charge", 2, "Minimum precursor charge to be considered."); @@ -87,10 +87,11 @@ using namespace OpenMS; vector all_mods; ModificationsDB::getInstance()->getAllSearchModifications(all_mods); - defaults_.setValue("modifications:fixed", ListUtils::create("Carbamidomethyl (C)", ','), "Fixed modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)'"); - defaults_.setValidStrings("modifications:fixed", all_mods); - defaults_.setValue("modifications:variable", ListUtils::create("Oxidation (M)", ','), "Variable modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Oxidation (M)'"); - defaults_.setValidStrings("modifications:variable", all_mods); + + defaults_.setValue("modifications:fixed", std::vector{"Carbamidomethyl (C)"}, "Fixed modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)'"); + defaults_.setValidStrings("modifications:fixed", ListUtils::create(all_mods)); + defaults_.setValue("modifications:variable", std::vector{"Oxidation (M)"}, "Variable modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Oxidation (M)'"); + defaults_.setValidStrings("modifications:variable", ListUtils::create(all_mods)); defaults_.setValue("modifications:variable_max_per_peptide", 3, "Maximum number of residues carrying a variable modification per candidate peptide"); defaults_.setSectionDescription("modifications", "Peptide modification settings"); @@ -98,12 +99,13 @@ using namespace OpenMS; defaults_.setValue("peptide:missed_cleavages", 3, "Number of missed cleavages."); vector all_enzymes; ProteaseDB::getInstance()->getAllNames(all_enzymes); + defaults_.setValue("peptide:enzyme", "Trypsin", "The enzyme used for peptide digestion."); - defaults_.setValidStrings("peptide:enzyme", all_enzymes); + defaults_.setValidStrings("peptide:enzyme", ListUtils::create(all_enzymes)); defaults_.setSectionDescription("peptide", "Settings for digesting proteins into peptides"); - defaults_.setValue("cross_linker:residue1", ListUtils::create("K,N-term"), "Comma separated residues, that the first side of a bifunctional cross-linker can attach to"); - defaults_.setValue("cross_linker:residue2", ListUtils::create("K,N-term"), "Comma separated residues, that the second side of a bifunctional cross-linker can attach to"); + defaults_.setValue("cross_linker:residue1", std::vector{"K","N-term"}, "Comma separated residues, that the first side of a bifunctional cross-linker can attach to"); + defaults_.setValue("cross_linker:residue2", std::vector{"K","N-term"}, "Comma separated residues, that the second side of a bifunctional cross-linker can attach to"); defaults_.setValue("cross_linker:mass_light", 138.0680796, "Mass of the light cross-linker, linking two residues on one or two peptides"); defaults_.setValue("cross_linker:mass_iso_shift", 12.075321, "Mass of the isotopic shift between the light and heavy linkers"); defaults_.setValue("cross_linker:mass_mono_link", ListUtils::create("156.07864431, 155.094628715"), "Possible masses of the linker, when attached to only one peptide"); @@ -111,18 +113,18 @@ using namespace OpenMS; defaults_.setSectionDescription("cross_linker", "Description of the cross-linker reagent"); defaults_.setValue("algorithm:number_top_hits", 1, "Number of top hits reported for each spectrum pair"); - StringList deisotope_strings = ListUtils::create("true,false,auto"); - defaults_.setValue("algorithm:deisotope", "auto", "Set to true, if the input spectra should be deisotoped before any other processing steps. If set to auto the spectra will be deisotoped, if the fragment mass tolerance is < 0.1 Da or < 100 ppm (0.1 Da at a mass of 1000)", ListUtils::create("advanced")); + std::vector deisotope_strings = {"true","false","auto"}; + defaults_.setValue("algorithm:deisotope", "auto", "Set to true, if the input spectra should be deisotoped before any other processing steps. If set to auto the spectra will be deisotoped, if the fragment mass tolerance is < 0.1 Da or < 100 ppm (0.1 Da at a mass of 1000)", {"advanced"}); defaults_.setValidStrings("algorithm:deisotope", deisotope_strings); defaults_.setSectionDescription("algorithm", "Additional algorithm settings"); - defaults_.setValue("ions:b_ions", "true", "Search for peaks of b-ions.", ListUtils::create("advanced")); - defaults_.setValue("ions:y_ions", "true", "Search for peaks of y-ions.", ListUtils::create("advanced")); - defaults_.setValue("ions:a_ions", "false", "Search for peaks of a-ions.", ListUtils::create("advanced")); - defaults_.setValue("ions:x_ions", "false", "Search for peaks of x-ions.", ListUtils::create("advanced")); - defaults_.setValue("ions:c_ions", "false", "Search for peaks of c-ions.", ListUtils::create("advanced")); - defaults_.setValue("ions:z_ions", "false", "Search for peaks of z-ions.", ListUtils::create("advanced")); - defaults_.setValue("ions:neutral_losses", "true", "Search for neutral losses of H2O and H3N.", ListUtils::create("advanced")); + defaults_.setValue("ions:b_ions", "true", "Search for peaks of b-ions.", {"advanced"}); + defaults_.setValue("ions:y_ions", "true", "Search for peaks of y-ions.", {"advanced"}); + defaults_.setValue("ions:a_ions", "false", "Search for peaks of a-ions.", {"advanced"}); + defaults_.setValue("ions:x_ions", "false", "Search for peaks of x-ions.", {"advanced"}); + defaults_.setValue("ions:c_ions", "false", "Search for peaks of c-ions.", {"advanced"}); + defaults_.setValue("ions:z_ions", "false", "Search for peaks of z-ions.", {"advanced"}); + defaults_.setValue("ions:neutral_losses", "true", "Search for neutral losses of H2O and H3N.", {"advanced"}); defaults_.setValidStrings("ions:b_ions", bool_strings); defaults_.setValidStrings("ions:y_ions", bool_strings); defaults_.setValidStrings("ions:a_ions", bool_strings); @@ -141,43 +143,43 @@ using namespace OpenMS; void OpenPepXLAlgorithm::updateMembers_() { - decoy_string_ = static_cast(param_.getValue("decoy_string")); - decoy_prefix_ = (param_.getValue("decoy_prefix") == "true" ? true : false); + decoy_string_ = param_.getValue("decoy_string").toString(); + decoy_prefix_ = param_.getValue("decoy_prefix").toBool(); - min_precursor_charge_ = static_cast(param_.getValue("precursor:min_charge")); - max_precursor_charge_ = static_cast(param_.getValue("precursor:max_charge")); - precursor_mass_tolerance_ = static_cast(param_.getValue("precursor:mass_tolerance")); - precursor_mass_tolerance_unit_ppm_ = (static_cast(param_.getValue("precursor:mass_tolerance_unit")) == "ppm"); + min_precursor_charge_ = param_.getValue("precursor:min_charge"); + max_precursor_charge_ = param_.getValue("precursor:max_charge"); + precursor_mass_tolerance_ = param_.getValue("precursor:mass_tolerance"); + precursor_mass_tolerance_unit_ppm_ = (param_.getValue("precursor:mass_tolerance_unit") == "ppm"); precursor_correction_steps_ = param_.getValue("precursor:corrections"); - fragment_mass_tolerance_ = static_cast(param_.getValue("fragment:mass_tolerance")); - fragment_mass_tolerance_xlinks_ = static_cast(param_.getValue("fragment:mass_tolerance_xlinks")); - fragment_mass_tolerance_unit_ppm_ = (static_cast(param_.getValue("fragment:mass_tolerance_unit")) == "ppm"); + fragment_mass_tolerance_ = param_.getValue("fragment:mass_tolerance"); + fragment_mass_tolerance_xlinks_ = param_.getValue("fragment:mass_tolerance_xlinks"); + fragment_mass_tolerance_unit_ppm_ = (param_.getValue("fragment:mass_tolerance_unit") == "ppm"); - cross_link_residue1_ = param_.getValue("cross_linker:residue1"); - cross_link_residue2_ = param_.getValue("cross_linker:residue2"); - cross_link_mass_light_ = static_cast(param_.getValue("cross_linker:mass_light")); - cross_link_mass_iso_shift_ = static_cast(param_.getValue("cross_linker:mass_iso_shift")); + cross_link_residue1_ = ListUtils::toStringList(param_.getValue("cross_linker:residue1")); + cross_link_residue2_ = ListUtils::toStringList(param_.getValue("cross_linker:residue2")); + cross_link_mass_light_ = param_.getValue("cross_linker:mass_light"); + cross_link_mass_iso_shift_ = param_.getValue("cross_linker:mass_iso_shift"); cross_link_mass_mono_link_ = param_.getValue("cross_linker:mass_mono_link"); - cross_link_name_ = static_cast(param_.getValue("cross_linker:name")); + cross_link_name_ = param_.getValue("cross_linker:name").toString(); - fixedModNames_ = param_.getValue("modifications:fixed"); - varModNames_ = param_.getValue("modifications:variable"); + fixedModNames_ = ListUtils::toStringList(param_.getValue("modifications:fixed")); + varModNames_ = ListUtils::toStringList(param_.getValue("modifications:variable")); max_variable_mods_per_peptide_ = static_cast(param_.getValue("modifications:variable_max_per_peptide")); peptide_min_size_ = static_cast(param_.getValue("peptide:min_size")); missed_cleavages_ = static_cast(param_.getValue("peptide:missed_cleavages")); - enzyme_name_ = static_cast(param_.getValue("peptide:enzyme")); - - number_top_hits_ = static_cast(param_.getValue("algorithm:number_top_hits")); - deisotope_mode_ = static_cast(param_.getValue("algorithm:deisotope")); - - add_y_ions_ = param_.getValue("ions:y_ions"); - add_b_ions_ = param_.getValue("ions:b_ions"); - add_x_ions_ = param_.getValue("ions:x_ions"); - add_a_ions_ = param_.getValue("ions:a_ions"); - add_c_ions_ = param_.getValue("ions:c_ions"); - add_z_ions_ = param_.getValue("ions:z_ions"); - add_losses_ = param_.getValue("ions:neutral_losses"); + enzyme_name_ = param_.getValue("peptide:enzyme").toString(); + + number_top_hits_ = param_.getValue("algorithm:number_top_hits"); + deisotope_mode_ = param_.getValue("algorithm:deisotope").toString(); + + add_y_ions_ = param_.getValue("ions:y_ions").toString(); + add_b_ions_ = param_.getValue("ions:b_ions").toString(); + add_x_ions_ = param_.getValue("ions:x_ions").toString(); + add_a_ions_ = param_.getValue("ions:a_ions").toString(); + add_c_ions_ = param_.getValue("ions:c_ions").toString(); + add_z_ions_ = param_.getValue("ions:z_ions").toString(); + add_losses_ = param_.getValue("ions:neutral_losses").toString(); } OpenPepXLAlgorithm::ExitCodes OpenPepXLAlgorithm::run(PeakMap& unprocessed_spectra, ConsensusMap& cfeatures, std::vector& fasta_db, std::vector& protein_ids, std::vector& peptide_ids, OPXLDataStructs::PreprocessedPairSpectra& preprocessed_pair_spectra, std::vector< std::pair >& spectrum_pairs, std::vector< std::vector< OPXLDataStructs::CrossLinkSpectrumMatch > >& all_top_csms, PeakMap& spectra) diff --git a/src/openms/source/ANALYSIS/XLMS/OpenPepXLLFAlgorithm.cpp b/src/openms/source/ANALYSIS/XLMS/OpenPepXLLFAlgorithm.cpp index bf0fb762d44..52ff320ac26 100644 --- a/src/openms/source/ANALYSIS/XLMS/OpenPepXLLFAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/XLMS/OpenPepXLLFAlgorithm.cpp @@ -64,12 +64,12 @@ using namespace OpenMS; : DefaultParamHandler("OpenPepXLLFAlgorithm") { defaults_.setValue("decoy_string", "DECOY_", "String that was appended (or prefixed - see 'prefix' flag below) to the accessions in the protein database to indicate decoy proteins."); - StringList bool_strings = StringList({"true", "false"}); + std::vector bool_strings = {"true", "false"}; defaults_.setValue("decoy_prefix", "true", "Set to true, if the decoy_string is a prefix of accessions in the protein database. Otherwise it is a suffix."); - defaults_.setValidStrings("decoy_prefix", bool_strings); + defaults_.setValidStrings("decoy_prefix", {"true", "false"}); defaults_.setValue("precursor:mass_tolerance", 10.0, "Width of precursor mass tolerance window"); - StringList mass_tolerance_unit_valid_strings = StringList({"ppm", "Da"}); + std::vector mass_tolerance_unit_valid_strings = {"ppm", "Da"}; defaults_.setValue("precursor:mass_tolerance_unit", "ppm", "Unit of precursor mass tolerance."); defaults_.setValidStrings("precursor:mass_tolerance_unit", mass_tolerance_unit_valid_strings); defaults_.setValue("precursor:min_charge", 2, "Minimum precursor charge to be considered."); @@ -85,10 +85,11 @@ using namespace OpenMS; vector all_mods; ModificationsDB::getInstance()->getAllSearchModifications(all_mods); - defaults_.setValue("modifications:fixed", StringList({"Carbamidomethyl (C)"}), "Fixed modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)'"); - defaults_.setValidStrings("modifications:fixed", all_mods); - defaults_.setValue("modifications:variable", StringList({"Oxidation (M)"}), "Variable modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Oxidation (M)'"); - defaults_.setValidStrings("modifications:variable", all_mods); + + defaults_.setValue("modifications:fixed", std::vector({"Carbamidomethyl (C)"}), "Fixed modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)'"); + defaults_.setValidStrings("modifications:fixed", ListUtils::create(all_mods)); + defaults_.setValue("modifications:variable", std::vector({"Oxidation (M)"}), "Variable modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Oxidation (M)'"); + defaults_.setValidStrings("modifications:variable", ListUtils::create(all_mods)); defaults_.setValue("modifications:variable_max_per_peptide", 3, "Maximum number of residues carrying a variable modification per candidate peptide"); defaults_.setSectionDescription("modifications", "Peptide modification settings"); @@ -96,33 +97,34 @@ using namespace OpenMS; defaults_.setValue("peptide:missed_cleavages", 3, "Number of missed cleavages."); vector all_enzymes; ProteaseDB::getInstance()->getAllNames(all_enzymes); + defaults_.setValue("peptide:enzyme", "Trypsin", "The enzyme used for peptide digestion."); - defaults_.setValidStrings("peptide:enzyme", all_enzymes); + defaults_.setValidStrings("peptide:enzyme", ListUtils::create(all_enzymes)); defaults_.setSectionDescription("peptide", "Settings for digesting proteins into peptides"); - defaults_.setValue("cross_linker:residue1", StringList({"K", "N-term"}), "Comma separated residues, that the first side of a bifunctional cross-linker can attach to"); - defaults_.setValue("cross_linker:residue2", StringList({"K", "N-term"}), "Comma separated residues, that the second side of a bifunctional cross-linker can attach to"); + defaults_.setValue("cross_linker:residue1", std::vector({"K", "N-term"}), "Comma separated residues, that the first side of a bifunctional cross-linker can attach to"); + defaults_.setValue("cross_linker:residue2", std::vector({"K", "N-term"}), "Comma separated residues, that the second side of a bifunctional cross-linker can attach to"); defaults_.setValue("cross_linker:mass", 138.0680796, "Mass of the light cross-linker, linking two residues on one or two peptides"); defaults_.setValue("cross_linker:mass_mono_link", DoubleList({156.07864431, 155.094628715}), "Possible masses of the linker, when attached to only one peptide"); defaults_.setValue("cross_linker:name", "DSS", "Name of the searched cross-link, used to resolve ambiguity of equal masses (e.g. DSS or BS3)"); defaults_.setSectionDescription("cross_linker", "Description of the cross-linker reagent"); defaults_.setValue("algorithm:number_top_hits", 1, "Number of top hits reported for each spectrum pair"); - StringList deisotope_strings = StringList({"true", "false", "auto"}); - defaults_.setValue("algorithm:deisotope", "auto", "Set to true, if the input spectra should be deisotoped before any other processing steps. If set to auto the spectra will be deisotoped, if the fragment mass tolerance is < 0.1 Da or < 100 ppm (0.1 Da at a mass of 1000)", StringList({"advanced"})); + std::vector deisotope_strings = std::vector({"true", "false", "auto"}); + defaults_.setValue("algorithm:deisotope", "auto", "Set to true, if the input spectra should be deisotoped before any other processing steps. If set to auto the spectra will be deisotoped, if the fragment mass tolerance is < 0.1 Da or < 100 ppm (0.1 Da at a mass of 1000)", std::vector({"advanced"})); defaults_.setValidStrings("algorithm:deisotope", deisotope_strings); defaults_.setValue("algorithm:use_sequence_tags", "false", "Use sequence tags (de novo sequencing of short fragments) to filter out candidates before scoring. This will make the search faster, but can impact the sensitivity positively or negatively, depending on the dataset."); defaults_.setValidStrings("algorithm:use_sequence_tags", bool_strings); - defaults_.setValue("algorithm:sequence_tag_min_length", 2, "Minimal length of sequence tags to use for filtering candidates. Longer tags will make the search faster but much less sensitive. Ignored if 'algorithm:use_sequence_tags' is false.", StringList({"advanced"})); + defaults_.setValue("algorithm:sequence_tag_min_length", 2, "Minimal length of sequence tags to use for filtering candidates. Longer tags will make the search faster but much less sensitive. Ignored if 'algorithm:use_sequence_tags' is false.", std::vector({"advanced"})); defaults_.setSectionDescription("algorithm", "Additional algorithm settings"); - defaults_.setValue("ions:b_ions", "true", "Search for peaks of b-ions.", StringList({"advanced"})); - defaults_.setValue("ions:y_ions", "true", "Search for peaks of y-ions.", StringList({"advanced"})); - defaults_.setValue("ions:a_ions", "false", "Search for peaks of a-ions.", StringList({"advanced"})); - defaults_.setValue("ions:x_ions", "false", "Search for peaks of x-ions.", StringList({"advanced"})); - defaults_.setValue("ions:c_ions", "false", "Search for peaks of c-ions.", StringList({"advanced"})); - defaults_.setValue("ions:z_ions", "false", "Search for peaks of z-ions.", StringList({"advanced"})); - defaults_.setValue("ions:neutral_losses", "true", "Search for neutral losses of H2O and H3N.", StringList({"advanced"})); + defaults_.setValue("ions:b_ions", "true", "Search for peaks of b-ions.", std::vector({"advanced"})); + defaults_.setValue("ions:y_ions", "true", "Search for peaks of y-ions.", std::vector({"advanced"})); + defaults_.setValue("ions:a_ions", "false", "Search for peaks of a-ions.", std::vector({"advanced"})); + defaults_.setValue("ions:x_ions", "false", "Search for peaks of x-ions.", std::vector({"advanced"})); + defaults_.setValue("ions:c_ions", "false", "Search for peaks of c-ions.", std::vector({"advanced"})); + defaults_.setValue("ions:z_ions", "false", "Search for peaks of z-ions.", std::vector({"advanced"})); + defaults_.setValue("ions:neutral_losses", "true", "Search for neutral losses of H2O and H3N.", std::vector({"advanced"})); defaults_.setValidStrings("ions:b_ions", bool_strings); defaults_.setValidStrings("ions:y_ions", bool_strings); defaults_.setValidStrings("ions:a_ions", bool_strings); @@ -141,44 +143,44 @@ using namespace OpenMS; void OpenPepXLLFAlgorithm::updateMembers_() { - decoy_string_ = static_cast(param_.getValue("decoy_string")); + decoy_string_ = static_cast(param_.getValue("decoy_string").toString()); decoy_prefix_ = param_.getValue("decoy_prefix") == "true"; min_precursor_charge_ = static_cast(param_.getValue("precursor:min_charge")); max_precursor_charge_ = static_cast(param_.getValue("precursor:max_charge")); precursor_mass_tolerance_ = static_cast(param_.getValue("precursor:mass_tolerance")); - precursor_mass_tolerance_unit_ppm_ = (static_cast(param_.getValue("precursor:mass_tolerance_unit")) == "ppm"); + precursor_mass_tolerance_unit_ppm_ = (static_cast(param_.getValue("precursor:mass_tolerance_unit").toString()) == "ppm"); precursor_correction_steps_ = param_.getValue("precursor:corrections"); fragment_mass_tolerance_ = static_cast(param_.getValue("fragment:mass_tolerance")); fragment_mass_tolerance_xlinks_ = static_cast(param_.getValue("fragment:mass_tolerance_xlinks")); - fragment_mass_tolerance_unit_ppm_ = (static_cast(param_.getValue("fragment:mass_tolerance_unit")) == "ppm"); + fragment_mass_tolerance_unit_ppm_ = (static_cast(param_.getValue("fragment:mass_tolerance_unit").toString()) == "ppm"); - cross_link_residue1_ = param_.getValue("cross_linker:residue1"); - cross_link_residue2_ = param_.getValue("cross_linker:residue2"); + cross_link_residue1_ = ListUtils::toStringList(param_.getValue("cross_linker:residue1")); + cross_link_residue2_ = ListUtils::toStringList(param_.getValue("cross_linker:residue2")); cross_link_mass_ = static_cast(param_.getValue("cross_linker:mass")); cross_link_mass_mono_link_ = param_.getValue("cross_linker:mass_mono_link"); - cross_link_name_ = static_cast(param_.getValue("cross_linker:name")); + cross_link_name_ = static_cast(param_.getValue("cross_linker:name").toString()); - fixedModNames_ = param_.getValue("modifications:fixed"); - varModNames_ = param_.getValue("modifications:variable"); + fixedModNames_ = ListUtils::toStringList(param_.getValue("modifications:fixed")); + varModNames_ = ListUtils::toStringList(param_.getValue("modifications:variable")); max_variable_mods_per_peptide_ = static_cast(param_.getValue("modifications:variable_max_per_peptide")); peptide_min_size_ = static_cast(param_.getValue("peptide:min_size")); missed_cleavages_ = static_cast(param_.getValue("peptide:missed_cleavages")); - enzyme_name_ = static_cast(param_.getValue("peptide:enzyme")); + enzyme_name_ = static_cast(param_.getValue("peptide:enzyme").toString()); number_top_hits_ = static_cast(param_.getValue("algorithm:number_top_hits")); - deisotope_mode_ = static_cast(param_.getValue("algorithm:deisotope")); + deisotope_mode_ = static_cast(param_.getValue("algorithm:deisotope").toString()); use_sequence_tags_ = param_.getValue("algorithm:use_sequence_tags") == "true"; sequence_tag_min_length_ = static_cast(param_.getValue("algorithm:sequence_tag_min_length")); - add_y_ions_ = param_.getValue("ions:y_ions"); - add_b_ions_ = param_.getValue("ions:b_ions"); - add_x_ions_ = param_.getValue("ions:x_ions"); - add_a_ions_ = param_.getValue("ions:a_ions"); - add_c_ions_ = param_.getValue("ions:c_ions"); - add_z_ions_ = param_.getValue("ions:z_ions"); - add_losses_ = param_.getValue("ions:neutral_losses"); + add_y_ions_ = param_.getValue("ions:y_ions").toString(); + add_b_ions_ = param_.getValue("ions:b_ions").toString(); + add_x_ions_ = param_.getValue("ions:x_ions").toString(); + add_a_ions_ = param_.getValue("ions:a_ions").toString(); + add_c_ions_ = param_.getValue("ions:c_ions").toString(); + add_z_ions_ = param_.getValue("ions:z_ions").toString(); + add_losses_ = param_.getValue("ions:neutral_losses").toString(); } OpenPepXLLFAlgorithm::ExitCodes OpenPepXLLFAlgorithm::run(PeakMap& unprocessed_spectra, std::vector& fasta_db, std::vector& protein_ids, std::vector& peptide_ids, std::vector< std::vector< OPXLDataStructs::CrossLinkSpectrumMatch > >& all_top_csms, PeakMap& spectra) diff --git a/src/openms/source/ANALYSIS/XLMS/XFDRAlgorithm.cpp b/src/openms/source/ANALYSIS/XLMS/XFDRAlgorithm.cpp index 1763a9c5d35..6816ad642c8 100644 --- a/src/openms/source/ANALYSIS/XLMS/XFDRAlgorithm.cpp +++ b/src/openms/source/ANALYSIS/XLMS/XFDRAlgorithm.cpp @@ -52,7 +52,7 @@ using namespace OpenMS; defaults_.setValue(param_minionsmatched_, 0, "Filter for minimum matched ions per peptide."); defaults_.setMinInt(param_minionsmatched_, 0); - StringList bool_strings = ListUtils::create("true,false"); + std::vector bool_strings = {"true","false"}; defaults_.setValue(param_uniquexl_, "false", "Calculate statistics based only on unique IDs. For a set of IDs from equal candidates (same pair of peptides, modifications and cross-linked positions), only the highest scoring hit will be considered. By default the score distribution will be estimated using all 1st ranked candidates."); defaults_.setValidStrings(param_uniquexl_, bool_strings); @@ -74,7 +74,7 @@ using namespace OpenMS; void XFDRAlgorithm::updateMembers_() { - decoy_string_ = static_cast(param_.getValue(param_decoy_string_)); + decoy_string_ = static_cast(param_.getValue(param_decoy_string_).toString()); arg_mindeltas_ = static_cast(param_.getValue(param_mindeltas_)); arg_minborder_ = static_cast(param_.getValue(param_minborder_)); arg_maxborder_ = static_cast(param_.getValue(param_maxborder_)); diff --git a/src/openms/source/APPLICATIONS/INIUpdater.cpp b/src/openms/source/APPLICATIONS/INIUpdater.cpp index a027e933409..fcd1c48c9c9 100644 --- a/src/openms/source/APPLICATIONS/INIUpdater.cpp +++ b/src/openms/source/APPLICATIONS/INIUpdater.cpp @@ -54,9 +54,10 @@ namespace OpenMS for (Param::ParamIterator it = ini.begin(); it != ini.end(); ++it) { - if (it.getName().toQString().count(':') == 1 && it.getName().hasSuffix(":version")) + String name = it.getName(); + if (name.toQString().count(':') == 1 && name.hasSuffix(":version")) { - tool_names.push_back(it.getName().prefix(':')); + tool_names.push_back(name.prefix(':')); } } return tool_names; diff --git a/src/openms/source/APPLICATIONS/ParameterInformation.cpp b/src/openms/source/APPLICATIONS/ParameterInformation.cpp index ba33c007190..e7cefe33b77 100644 --- a/src/openms/source/APPLICATIONS/ParameterInformation.cpp +++ b/src/openms/source/APPLICATIONS/ParameterInformation.cpp @@ -36,7 +36,7 @@ namespace OpenMS { - ParameterInformation::ParameterInformation(const String& n, ParameterTypes t, const String& arg, const DataValue& def, const String& desc, bool req, bool adv, const StringList& tag_values) : + ParameterInformation::ParameterInformation(const String& n, ParameterTypes t, const String& arg, const ParamValue& def, const String& desc, bool req, bool adv, const StringList& tag_values) : name(n), type(t), default_value(def), diff --git a/src/openms/source/APPLICATIONS/TOPPBase.cpp b/src/openms/source/APPLICATIONS/TOPPBase.cpp index e6f8bc0e3d9..8e4f631e7e8 100755 --- a/src/openms/source/APPLICATIONS/TOPPBase.cpp +++ b/src/openms/source/APPLICATIONS/TOPPBase.cpp @@ -171,7 +171,7 @@ namespace OpenMS TOPPBase::~TOPPBase() { // delete log file if empty - String topplog = getParam_("log"); + const std::string& topplog = getParam_("log").toString(); if (!topplog.empty() && File::empty(topplog)) { File::remove(topplog); @@ -279,17 +279,17 @@ namespace OpenMS // '-write_ini' given if (param_cmdline_.exists("write_ini")) { - String write_ini_file = param_cmdline_.getValue("write_ini"); + String write_ini_file = param_cmdline_.getValue("write_ini").toString(); outputFileWritable_(write_ini_file, "write_ini"); Param default_params = getDefaultParameters_(); // check if augmentation with -ini param is needed - DataValue in_ini; + ParamValue in_ini; if (param_cmdline_.exists("ini")) { in_ini = param_cmdline_.getValue("ini"); Param ini_params; - ParamXMLFile().load((String)in_ini, ini_params); + ParamXMLFile().load(in_ini.toString(), ini_params); // check if ini parameters are applicable to this tool checkIfIniParametersAreApplicable_(ini_params); // update default params with outdated params given in -ini and be verbose @@ -315,15 +315,15 @@ namespace OpenMS // load INI file //------------------------------------------------------------- { - DataValue value_ini; + String value_ini; if (param_cmdline_.exists("ini")) { - value_ini = param_cmdline_.getValue("ini"); - writeDebug_("INI file: " + (String)value_ini, 1); + value_ini = param_cmdline_.getValue("ini").toString(); + writeDebug_("INI file: " + value_ini, 1); writeDebug_("INI location: " + getIniLocation_(), 1); - ParamXMLFile().load((String)value_ini, param_inifile_); + ParamXMLFile().load(value_ini, param_inifile_); checkIfIniParametersAreApplicable_(param_inifile_); // dissect loaded INI parameters @@ -377,16 +377,16 @@ namespace OpenMS } // check if all parameters are registered and have the correct type - checkParam_(param_instance_, (String)value_ini, getIniLocation_()); - checkParam_(param_common_tool_, (String)value_ini, "common:" + tool_name_ + "::"); - checkParam_(param_common_, (String)value_ini, "common:"); + checkParam_(param_instance_, value_ini, getIniLocation_()); + checkParam_(param_common_tool_, value_ini, "common:" + tool_name_ + "::"); + checkParam_(param_common_, value_ini, "common:"); // check if the version of the parameters file matches the version of this tool // the parameters and values are all ok, but there might be more valid values now or new parameters which are currently not visible in the outdated INI String file_version = ""; if (param_inifile_.exists(tool_name_ + ":version")) { - file_version = param_inifile_.getValue(tool_name_ + ":version"); + file_version = param_inifile_.getValue(tool_name_ + ":version").toString(); if (file_version != version_) { writeLog_(String("Warning: Parameters file version (") + file_version + ") does not match the version of this tool (" + version_ + ").\n" @@ -643,7 +643,7 @@ namespace OpenMS case ParameterInformation::INTLIST: case ParameterInformation::DOUBLELIST: { - String tmp_s = it->default_value.toString().substitute(", ", " "); + String tmp_s = ((String)it->default_value.toString()).substitute(", ", " "); if (tmp_s != "" && tmp_s != "[]") { addons.push_back(String("default: '") + tmp_s + "'"); @@ -758,7 +758,7 @@ namespace OpenMS String name = full_name.empty() ? entry.name : full_name; bool advanced = entry.tags.count("advanced"); // special case for flags: - if ((entry.value.valueType() == DataValue::STRING_VALUE) && + if ((entry.value.valueType() == ParamValue::STRING_VALUE) && /*entry.tags.count("flag") && */ // This would avoid autoconversion from true/false String Params when they default to false (entry.value == "false") && // This is the current default (entry.valid_strings.size() == 2) && @@ -776,7 +776,7 @@ namespace OpenMS enum ParameterInformation::ParameterTypes type = ParameterInformation::NONE; switch (entry.value.valueType()) { - case DataValue::STRING_VALUE: + case ParamValue::STRING_VALUE: if (input_file) type = ParameterInformation::INPUT_FILE; else if (output_file) @@ -785,15 +785,15 @@ namespace OpenMS type = ParameterInformation::STRING; break; - case DataValue::INT_VALUE: + case ParamValue::INT_VALUE: type = ParameterInformation::INT; break; - case DataValue::DOUBLE_VALUE: + case ParamValue::DOUBLE_VALUE: type = ParameterInformation::DOUBLE; break; - case DataValue::STRING_LIST: + case ParamValue::STRING_LIST: if (input_file) type = ParameterInformation::INPUT_FILE_LIST; else if (output_file) @@ -802,21 +802,21 @@ namespace OpenMS type = ParameterInformation::STRINGLIST; break; - case DataValue::INT_LIST: + case ParamValue::INT_LIST: type = ParameterInformation::INTLIST; break; - case DataValue::DOUBLE_LIST: + case ParamValue::DOUBLE_LIST: type = ParameterInformation::DOUBLELIST; break; - case DataValue::EMPTY_VALUE: + case ParamValue::EMPTY_VALUE: type = ParameterInformation::NONE; break; } bool required = entry.tags.count("required"); ParameterInformation param(name, type, argument, entry.value, entry.description, required, advanced); - param.valid_strings = entry.valid_strings; + param.valid_strings = ListUtils::toStringList(entry.valid_strings); // here, we rely on the fact that defaults (meaning "not set") are the same for both: param.min_int = entry.min_int; param.max_int = entry.max_int; @@ -830,34 +830,34 @@ namespace OpenMS String argument = ""; switch (entry.value.valueType()) { - case DataValue::STRING_VALUE: + case ParamValue::STRING_VALUE: if (entry.valid_strings.empty()) argument = ""; // name? else argument = ""; break; - case DataValue::INT_VALUE: + case ParamValue::INT_VALUE: argument = ""; // integer? break; - case DataValue::DOUBLE_VALUE: + case ParamValue::DOUBLE_VALUE: argument = ""; // float? break; - case DataValue::STRING_LIST: + case ParamValue::STRING_LIST: argument = ""; break; - case DataValue::INT_LIST: + case ParamValue::INT_LIST: argument = ""; break; - case DataValue::DOUBLE_LIST: + case ParamValue::DOUBLE_LIST: argument = ""; break; - case DataValue::EMPTY_VALUE: + case ParamValue::EMPTY_VALUE: argument = ""; break; } @@ -953,18 +953,17 @@ namespace OpenMS StringList defaults; if (p.type == ParameterInformation::STRING) - defaults.push_back(String(p.default_value)); + defaults.push_back(String(p.default_value.toString())); else - defaults = p.default_value; + defaults = ListUtils::toStringList(p.default_value); for (Size j = 0; j < defaults.size(); ++j) // allow the empty string even if not in restrictions { if (defaults[j].size() > 0 && !ListUtils::contains(valids, defaults[j])) { - throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TO THE DEVELOPER: The TOPP/UTILS tool option '" + name + "' with default value " + String(p.default_value) + " does not meet restrictions!"); + throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TO THE DEVELOPER: The TOPP/UTILS tool option '" + name + "' with default value " + std::string(p.default_value) + " does not meet restrictions!"); } } - p.valid_strings = strings; } @@ -1023,7 +1022,7 @@ namespace OpenMS { if (defaults[j] < min) { - throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TO THE DEVELOPER: The TOPP/UTILS tool option '" + name + "' with default value " + String(p.default_value) + " does not meet restrictions!"); + throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TO THE DEVELOPER: The TOPP/UTILS tool option '" + name + "' with default value " + std::string(p.default_value) + " does not meet restrictions!"); } } p.min_int = min; @@ -1047,7 +1046,7 @@ namespace OpenMS { if (defaults[j] > max) { - throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TO THE DEVELOPER: The TOPP/UTILS tool option '" + name + "' with default value " + String(p.default_value) + " does not meet restrictions!"); + throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TO THE DEVELOPER: The TOPP/UTILS tool option '" + name + "' with default value " + std::string(p.default_value) + " does not meet restrictions!"); } } p.max_int = max; @@ -1071,7 +1070,7 @@ namespace OpenMS { if (defaults[j] < min) { - throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TO THE DEVELOPER: The TOPP/UTILS tool option '" + name + "' with default value " + String(p.default_value) + " does not meet restrictions!"); + throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TO THE DEVELOPER: The TOPP/UTILS tool option '" + name + "' with default value " + std::string(p.default_value) + " does not meet restrictions!"); } } p.min_float = min; @@ -1095,7 +1094,7 @@ namespace OpenMS { if (defaults[j] > max) { - throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TO THE DEVELOPER: The TOPP/UTILS tool option '" + name + "' with default value " + String(p.default_value) + " does not meet restrictions!"); + throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "TO THE DEVELOPER: The TOPP/UTILS tool option '" + name + "' with default value " + std::string(p.default_value) + " does not meet restrictions!"); } } p.max_float = max; @@ -1142,7 +1141,7 @@ namespace OpenMS { if (required && default_value.size() > 0) throw InvalidValue(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Registering a required OutputFileList param (" + name + ") with a non-empty default is forbidden!", ListUtils::concatenate(default_value, ",")); - parameters_.push_back(ParameterInformation(name, ParameterInformation::OUTPUT_FILE_LIST, argument, default_value, description, required, advanced)); + parameters_.push_back(ParameterInformation(name, ParameterInformation::OUTPUT_FILE_LIST, argument, ListUtils::create(default_value), description, required, advanced)); } void TOPPBase::registerInputFileList_(const String& name, const String& argument, StringList default_value, const String& description, bool required, bool advanced, const StringList& tags) @@ -1154,14 +1153,14 @@ namespace OpenMS } if (required && !default_value.empty() && count_conflicting_tags == 0) throw InvalidValue(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Registering a required InputFileList param (" + name + ") with a non-empty default is forbidden!", ListUtils::concatenate(default_value, ",")); - parameters_.push_back(ParameterInformation(name, ParameterInformation::INPUT_FILE_LIST, argument, default_value, description, required, advanced, tags)); + parameters_.push_back(ParameterInformation(name, ParameterInformation::INPUT_FILE_LIST, argument, ListUtils::create(default_value), description, required, advanced, tags)); } void TOPPBase::registerStringList_(const String& name, const String& argument, StringList default_value, const String& description, bool required, bool advanced) { if (required && default_value.size() > 0) throw InvalidValue(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Registering a required StringList param (" + name + ") with a non-empty default is forbidden!", ListUtils::concatenate(default_value, ",")); - parameters_.push_back(ParameterInformation(name, ParameterInformation::STRINGLIST, argument, default_value, description, required, advanced)); + parameters_.push_back(ParameterInformation(name, ParameterInformation::STRINGLIST, argument, ListUtils::create(default_value), description, required, advanced)); } void TOPPBase::registerIntList_(const String& name, const String& argument, IntList default_value, const String& description, bool required, bool advanced) @@ -1227,7 +1226,7 @@ namespace OpenMS } throw RequiredParameterNotGiven(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, message); } - String tmp = getParamAsString_(name, p.default_value); + String tmp = getParamAsString_(name, p.default_value.toString()); writeDebug_(String("Value of string option '") + name + "': " + tmp, 1); // if required or set by user, do some validity checks @@ -1317,9 +1316,11 @@ namespace OpenMS } else if (!ListUtils::contains(p.valid_strings, FileTypes::typeToName(f_type).toUpper(), ListUtils::CASE::INSENSITIVE)) { - throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, - String("Input file '" + t + "' has invalid format '") + FileTypes::typeToName(f_type) + - "'. Valid formats are: '" + ListUtils::concatenate(p.valid_strings, "','") + "'."); + throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, + String("Input file '" + t + "' has invalid format '") + + FileTypes::typeToName(f_type) + + "'. Valid formats are: '" + ListUtils::concatenate(p.valid_strings, "','") + + "'."); } } } @@ -1377,9 +1378,11 @@ namespace OpenMS } else if (!ListUtils::contains(p.valid_strings, FileTypes::typeToName(f_type).toUpper(), ListUtils::CASE::INSENSITIVE)) { - throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, - String("Input file '" + param_value + "' has invalid format '") + FileTypes::typeToName(f_type) + - "'. Valid formats are: '" + ListUtils::concatenate(p.valid_strings, "','") + "'."); + throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, + String("Input file '" + param_value + "' has invalid format '") + + FileTypes::typeToName(f_type) + + "'. Valid formats are: '" + ListUtils::concatenate(p.valid_strings, "','") + + "'."); } break; } @@ -1413,7 +1416,7 @@ namespace OpenMS { throw RequiredParameterNotGiven(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, name); } - StringList tmp_list = getParamAsStringList_(name, p.default_value); + StringList tmp_list = getParamAsStringList_(name, ListUtils::toStringList(p.default_value)); if (p.required && tmp_list.empty()) { throw RequiredParameterNotGiven(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, name); @@ -1425,7 +1428,7 @@ namespace OpenMS } // if required or set by user, do some validity checks - if (p.required || (!getParam_(name).isEmpty() && tmp_list != p.default_value)) + if (p.required || (!getParam_(name).isEmpty() && tmp_list != ListUtils::toStringList(p.default_value))) { fileParamValidityCheck_(tmp_list, name, p); } @@ -1577,7 +1580,7 @@ namespace OpenMS String TOPPBase::getParamAsString_(const String& key, const String& default_value) const { - const DataValue& tmp = getParam_(key); + const ParamValue& tmp = getParam_(key); if (!tmp.isEmpty()) { return tmp.toString(); @@ -1590,10 +1593,10 @@ namespace OpenMS Int TOPPBase::getParamAsInt_(const String& key, Int default_value) const { - const DataValue& tmp = getParam_(key); + const ParamValue& tmp = getParam_(key); if (!tmp.isEmpty()) { - if (tmp.valueType() == DataValue::INT_VALUE) + if (tmp.valueType() == ParamValue::INT_VALUE) { return (Int)tmp; } @@ -1607,10 +1610,10 @@ namespace OpenMS double TOPPBase::getParamAsDouble_(const String& key, double default_value) const { - const DataValue& tmp = getParam_(key); + const ParamValue& tmp = getParam_(key); if (!tmp.isEmpty()) { - if (tmp.valueType() == DataValue::DOUBLE_VALUE) + if (tmp.valueType() == ParamValue::DOUBLE_VALUE) { return (double)tmp; } @@ -1624,10 +1627,10 @@ namespace OpenMS StringList TOPPBase::getParamAsStringList_(const String& key, const StringList& default_value) const { - const DataValue& tmp = getParam_(key); + const ParamValue& tmp = getParam_(key); if (!tmp.isEmpty()) { - return tmp; + return ListUtils::toStringList(tmp); } else { @@ -1637,10 +1640,10 @@ namespace OpenMS IntList TOPPBase::getParamAsIntList_(const String& key, const IntList& default_value) const { - const DataValue& tmp = getParam_(key); + const ParamValue& tmp = getParam_(key); if (!tmp.isEmpty()) { - if (tmp.valueType() == DataValue::INT_LIST) + if (tmp.valueType() == ParamValue::INT_LIST) { return tmp; } @@ -1654,10 +1657,10 @@ namespace OpenMS DoubleList TOPPBase::getParamAsDoubleList_(const String& key, const DoubleList& default_value) const { - const DataValue& tmp = getParam_(key); + const ParamValue& tmp = getParam_(key); if (!tmp.isEmpty()) { - if (tmp.valueType() == DataValue::DOUBLE_LIST) + if (tmp.valueType() == ParamValue::DOUBLE_LIST) { return tmp; } @@ -1671,26 +1674,26 @@ namespace OpenMS bool TOPPBase::getParamAsBool_(const String& key) const { - DataValue tmp = getParam_(key); - if (tmp.valueType() == DataValue::EMPTY_VALUE) + ParamValue tmp = getParam_(key); + if (tmp.valueType() == ParamValue::EMPTY_VALUE) { return false; } - else if (tmp.valueType() == DataValue::STRING_VALUE) + else if (tmp.valueType() == ParamValue::STRING_VALUE) { - if ((String)tmp == "false") + if ((std::string)tmp == "false") { return false; } - else if ((String)tmp == "true") + else if ((std::string)tmp == "true") { return true; } } - throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("Invalid value '") + tmp.toString() + "' for flag parameter '" + key + "'. Valid values are 'true' and 'false' only."); + throw InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, std::string("Invalid value '") + (std::string)tmp + "' for flag parameter '" + key + "'. Valid values are 'true' and 'false' only."); } - DataValue const& TOPPBase::getParam_(const String& key) const + ParamValue const& TOPPBase::getParam_(const String& key) const { if (param_.exists(key)) { @@ -1700,7 +1703,7 @@ namespace OpenMS { // if look up fails everywhere, return EMPTY writeDebug_(String("Parameter '") + key + String("' not found."), 1); - return DataValue::EMPTY; + return ParamValue::EMPTY; } } @@ -1722,7 +1725,7 @@ namespace OpenMS { if (log_.is_open() || !param_.exists("log")) return; - String log_destination = param_.getValue("log"); + std::string log_destination = param_.getValue("log"); if (log_destination.empty()) return; log_.open(log_destination, ofstream::out | ofstream::app); if (debug_level_ >= 1) @@ -1762,21 +1765,21 @@ namespace OpenMS case ParameterInformation::INPUT_FILE: case ParameterInformation::OUTPUT_FILE: case ParameterInformation::FLAG: - if (it->value.valueType() != DataValue::STRING_VALUE) + if (it->value.valueType() != ParamValue::STRING_VALUE) { writeLog_("Warning: Wrong parameter type of '" + location + it.getName() + "' in '" + filename + "'. Type should be 'string'!"); } break; case ParameterInformation::DOUBLE: - if (it->value.valueType() != DataValue::DOUBLE_VALUE) + if (it->value.valueType() != ParamValue::DOUBLE_VALUE) { writeLog_("Warning: Wrong parameter type of '" + location + it.getName() + "' in '" + filename + "'. Type should be 'double'!"); } break; case ParameterInformation::INT: - if (it->value.valueType() != DataValue::INT_VALUE) + if (it->value.valueType() != ParamValue::INT_VALUE) { writeLog_("Warning: Wrong parameter type of '" + location + it.getName() + "' in '" + filename + "'. Type should be 'int'!"); } @@ -1785,21 +1788,21 @@ namespace OpenMS case ParameterInformation::STRINGLIST: case ParameterInformation::INPUT_FILE_LIST: case ParameterInformation::OUTPUT_FILE_LIST: - if (it->value.valueType() != DataValue::STRING_LIST) + if (it->value.valueType() != ParamValue::STRING_LIST) { writeLog_("Warning: Wrong parameter type of '" + location + it.getName() + "' in '" + filename + "'. Type should be 'string list'!"); } break; case ParameterInformation::INTLIST: - if (it->value.valueType() != DataValue::INT_LIST) + if (it->value.valueType() != ParamValue::INT_LIST) { writeLog_("Warning: Wrong parameter type of '" + location + it.getName() + "' in '" + filename + "'. Type should be 'int list'!"); } break; case ParameterInformation::DOUBLELIST: - if (it->value.valueType() != DataValue::DOUBLE_LIST) + if (it->value.valueType() != ParamValue::DOUBLE_LIST) { writeLog_("Warning: Wrong parameter type of '" + location + it.getName() + "' in '" + filename + "'. Type should be 'double list'!"); } @@ -1956,7 +1959,7 @@ namespace OpenMS continue; } String name = loc + it->name; - StringList tags; + std::vector tags; if (it->advanced) tags.push_back("advanced"); if (it->required) @@ -1969,21 +1972,21 @@ namespace OpenMS switch (it->type) { case ParameterInformation::STRING: - tmp.setValue(name, (String)it->default_value, it->description, tags); + tmp.setValue(name, (String)it->default_value.toString(), it->description, tags); if (it->valid_strings.size() != 0) { - tmp.setValidStrings(name, it->valid_strings); + tmp.setValidStrings(name, ListUtils::create(it->valid_strings)); } break; case ParameterInformation::INPUT_FILE: case ParameterInformation::OUTPUT_FILE: - tmp.setValue(name, (String)it->default_value, it->description, tags); + tmp.setValue(name, (String)it->default_value.toString(), it->description, tags); if (it->valid_strings.size() != 0) { StringList vss_tmp = it->valid_strings; - StringList vss; - foreach(String vs, vss_tmp) + std::vector vss; + foreach(std::string vs, vss_tmp) { vss.push_back("*." + vs); } @@ -2025,8 +2028,8 @@ namespace OpenMS tmp.setValue(name, it->default_value, it->description, tags); if (it->valid_strings.size() != 0) { - StringList vss = it->valid_strings; - std::transform(vss.begin(), vss.end(), vss.begin(), [](const String& s) {return "*." + s;}); + std::vector vss = ListUtils::create(it->valid_strings); + std::transform(vss.begin(), vss.end(), vss.begin(), [](const std::string& s) {return "*." + s;}); tmp.setValidStrings(name, vss); } break; @@ -2035,7 +2038,7 @@ namespace OpenMS tmp.setValue(name, it->default_value, it->description, tags); if (it->valid_strings.size() != 0) { - tmp.setValidStrings(name, it->valid_strings); + tmp.setValidStrings(name, ListUtils::create(it->valid_strings)); } break; @@ -2075,7 +2078,7 @@ namespace OpenMS } // set tool version - tmp.setValue(tool_name_ + ":version", version_, "Version of the tool that generated this parameters file.", ListUtils::create("advanced")); + tmp.setValue(tool_name_ + ":version", version_, "Version of the tool that generated this parameters file.", {"advanced"}); // Descriptions tmp.setSectionDescription(tool_name_, tool_description_); @@ -2176,7 +2179,7 @@ namespace OpenMS const Param& param = getParam_(); for (Param::ParamIterator it = param.begin(); it != param.end(); ++it) { - p.setMetaValue(String("parameter: ") + it.getName(), it->value); + p.setMetaValue(String("parameter: " + it.getName()), it->value); } } @@ -2237,7 +2240,7 @@ namespace OpenMS bool TOPPBase::writeCTD_() { //store ini-file content in ini_file_str - QString out_dir_str = String(param_cmdline_.getValue("write_ctd")).toQString(); + QString out_dir_str = String(param_cmdline_.getValue("write_ctd").toString()).toQString(); if (out_dir_str == "") { out_dir_str = QDir::currentPath(); @@ -2348,7 +2351,7 @@ namespace OpenMS } // list to store "misc"/"unknown" items: - map misc_unknown; + map > misc_unknown; list queue; // queue for arguments // we parse the arguments in reverse order, so that we have arguments already when we encounter the option that uses them! @@ -2362,10 +2365,10 @@ namespace OpenMS ParamMap::iterator pos = param_map.find(arg); if (pos != param_map.end()) // parameter is defined { - DataValue value; + ParamValue value; if (pos->second->type == ParameterInformation::FLAG) // flag { - value = String("true"); + value = "true"; } else // option with argument(s) { @@ -2375,7 +2378,7 @@ namespace OpenMS case ParameterInformation::INPUT_FILE: case ParameterInformation::OUTPUT_FILE: if (queue.empty()) - value = String(); + value = std::string(); else value = queue.front(); break; @@ -2394,8 +2397,8 @@ namespace OpenMS case ParameterInformation::OUTPUT_FILE_LIST: case ParameterInformation::STRINGLIST: { - vector arg_list(queue.begin(), queue.end()); - value = StringList(arg_list); + vector arg_list(queue.begin(), queue.end()); + value = arg_list; queue.clear(); break; } @@ -2438,7 +2441,7 @@ namespace OpenMS misc_unknown[unknown].push_back(arg); } // rest of the queue is just text -> insert into "misc" list: - StringList& misc_list = misc_unknown[misc]; + std::vector& misc_list = misc_unknown[misc]; misc_list.insert(misc_list.begin(), queue.begin(), queue.end()); queue.clear(); } @@ -2448,11 +2451,11 @@ namespace OpenMS } } // remaining items in the queue are leading text arguments: - StringList& misc_list = misc_unknown[misc]; + std::vector& misc_list = misc_unknown[misc]; misc_list.insert(misc_list.begin(), queue.begin(), queue.end()); // store "misc"/"unknown" items, if there were any: - for (map::iterator it = misc_unknown.begin(); + for (map >::iterator it = misc_unknown.begin(); it != misc_unknown.end(); ++it) { if (it->second.empty()) @@ -2464,7 +2467,7 @@ namespace OpenMS } else { - StringList new_value = cmd_params.getValue(it->first); + std::vector new_value = cmd_params.getValue(it->first); new_value.insert(new_value.end(), it->second.begin(), it->second.end()); cmd_params.setValue(it->first, new_value); } diff --git a/src/openms/source/APPLICATIONS/ToolHandler.cpp b/src/openms/source/APPLICATIONS/ToolHandler.cpp index 4047025c806..a6ea60f20dd 100644 --- a/src/openms/source/APPLICATIONS/ToolHandler.cpp +++ b/src/openms/source/APPLICATIONS/ToolHandler.cpp @@ -84,7 +84,6 @@ namespace OpenMS tools_map["IDRTCalibration"] = Internal::ToolDescription("IDRTCalibration", "ID Processing"); tools_map["IsobaricAnalyzer"] = Internal::ToolDescription("IsobaricAnalyzer", "Quantitation"); tools_map["InclusionExclusionListCreator"] = Internal::ToolDescription("InclusionExclusionListCreator", "Targeted Experiments"); - tools_map["InspectAdapter"] = Internal::ToolDescription("InspectAdapter", "Identification"); tools_map["InternalCalibration"] = Internal::ToolDescription("InternalCalibration", "Signal processing and preprocessing"); tools_map["LuciphorAdapter"] = Internal::ToolDescription("LuciphorAdapter", "ID Processing"); tools_map["MapAlignerIdentification"] = Internal::ToolDescription("MapAlignerIdentification", "Map Alignment"); diff --git a/src/openms/source/CHEMISTRY/ElementDB.cpp b/src/openms/source/CHEMISTRY/ElementDB.cpp index 037ef1bfc42..4bca7655c72 100644 --- a/src/openms/source/CHEMISTRY/ElementDB.cpp +++ b/src/openms/source/CHEMISTRY/ElementDB.cpp @@ -231,7 +231,7 @@ namespace OpenMS // determine prefix vector split; - param.begin().getName().split(':', split); + String(param.begin().getName()).split(':', split); String prefix(""); for (Size i = 0; i < split.size() - 1; ++i) { @@ -242,10 +242,10 @@ namespace OpenMS for (Param::ParamIterator it = param.begin(); it != param.end(); ++it) { - it.getName().split(':', split); + String(it.getName()).split(':', split); // new element started? - if (!it.getName().hasPrefix(prefix)) + if (it.getName().compare(0, prefix.size(), prefix) != 0) { // update prefix prefix = ""; @@ -263,7 +263,7 @@ namespace OpenMS // top level: read the contents of the element section const String& key = split[2]; - String value = it->value; + String value = String(it->value.toString()); value.trim(); // cout << "Key=" << key << endl; diff --git a/src/openms/source/CHEMISTRY/MASSDECOMPOSITION/MassDecompositionAlgorithm.cpp b/src/openms/source/CHEMISTRY/MASSDECOMPOSITION/MassDecompositionAlgorithm.cpp index d83e7185cb7..44102646963 100644 --- a/src/openms/source/CHEMISTRY/MASSDECOMPOSITION/MassDecompositionAlgorithm.cpp +++ b/src/openms/source/CHEMISTRY/MASSDECOMPOSITION/MassDecompositionAlgorithm.cpp @@ -48,18 +48,18 @@ namespace OpenMS alphabet_(nullptr), decomposer_(nullptr) { - defaults_.setValue("decomp_weights_precision", 0.01, "precision used to calculate the decompositions, this only affects cache usage!", ListUtils::create("advanced")); + defaults_.setValue("decomp_weights_precision", 0.01, "precision used to calculate the decompositions, this only affects cache usage!", {"advanced"}); defaults_.setValue("tolerance", 0.3, "tolerance which is allowed for the decompositions"); vector all_mods; ModificationsDB::getInstance()->getAllSearchModifications(all_mods); - defaults_.setValue("fixed_modifications", ListUtils::create(""), "fixed modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)' or 'Oxidation (M)'"); - defaults_.setValidStrings("fixed_modifications", all_mods); - defaults_.setValue("variable_modifications", ListUtils::create(""), "variable modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)' or 'Oxidation (M)'"); - defaults_.setValidStrings("variable_modifications", all_mods); - defaults_.setValue("residue_set", "Natural19WithoutI", "The predefined amino acid set that should be used, see doc of ResidueDB for possible residue sets", ListUtils::create("advanced")); + defaults_.setValue("fixed_modifications", std::vector(), "fixed modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)' or 'Oxidation (M)'"); + defaults_.setValidStrings("fixed_modifications", ListUtils::create(all_mods)); + defaults_.setValue("variable_modifications", std::vector(), "variable modifications, specified using UniMod (www.unimod.org) terms, e.g. 'Carbamidomethyl (C)' or 'Oxidation (M)'"); + defaults_.setValidStrings("variable_modifications", ListUtils::create(all_mods)); + defaults_.setValue("residue_set", "Natural19WithoutI", "The predefined amino acid set that should be used, see doc of ResidueDB for possible residue sets", {"advanced"}); set residue_sets = ResidueDB::getInstance()->getResidueSets(); - vector valid_strings; + vector valid_strings; for (set::const_iterator it = residue_sets.begin(); it != residue_sets.end(); ++it) { valid_strings.push_back(*it); @@ -103,7 +103,7 @@ namespace OpenMS Map aa_to_weight; - set residues = ResidueDB::getInstance()->getResidues((String)param_.getValue("residue_set")); + set residues = ResidueDB::getInstance()->getResidues(String(param_.getValue("residue_set").toString())); for (set::const_iterator it = residues.begin(); it != residues.end(); ++it) { @@ -111,7 +111,7 @@ namespace OpenMS } // now handle the modifications - ModificationDefinitionsSet mod_set(param_.getValue("fixed_modifications"), param_.getValue("variable_modifications")); + ModificationDefinitionsSet mod_set(ListUtils::toStringList(param_.getValue("fixed_modifications")), ListUtils::toStringList(param_.getValue("variable_modifications"))); set fixed_mods = mod_set.getFixedModifications(); for (set::const_iterator it = fixed_mods.begin(); it != fixed_mods.end(); ++it) { diff --git a/src/openms/source/CHEMISTRY/NucleicAcidSpectrumGenerator.cpp b/src/openms/source/CHEMISTRY/NucleicAcidSpectrumGenerator.cpp index 63fa47f8564..cf20c36ffc7 100644 --- a/src/openms/source/CHEMISTRY/NucleicAcidSpectrumGenerator.cpp +++ b/src/openms/source/CHEMISTRY/NucleicAcidSpectrumGenerator.cpp @@ -46,43 +46,43 @@ namespace OpenMS DefaultParamHandler("NucleicAcidSpectrumGenerator") { defaults_.setValue("add_metainfo", "false", "Adds the type of peaks as meta information to the peaks, e.g. c1, y2, a3-B"); - defaults_.setValidStrings("add_metainfo", ListUtils::create("true,false")); + defaults_.setValidStrings("add_metainfo", {"true","false"}); defaults_.setValue("add_precursor_peaks", "false", "Adds peaks of the unfragmented precursor ion to the spectrum"); - defaults_.setValidStrings("add_precursor_peaks", ListUtils::create("true,false")); + defaults_.setValidStrings("add_precursor_peaks", {"true","false"}); defaults_.setValue("add_all_precursor_charges", "false", "Adds precursor peaks with all charges in the given range"); - defaults_.setValidStrings("add_all_precursor_charges", ListUtils::create("true,false")); + defaults_.setValidStrings("add_all_precursor_charges", {"true","false"}); defaults_.setValue("add_first_prefix_ion", "false", "If set to true a1, b1, ..., z1 ions are added"); - defaults_.setValidStrings("add_first_prefix_ion", ListUtils::create("true,false")); + defaults_.setValidStrings("add_first_prefix_ion", {"true","false"}); defaults_.setValue("add_a_ions", "false", "Add peaks of a-ions to the spectrum"); - defaults_.setValidStrings("add_a_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_a_ions", {"true","false"}); defaults_.setValue("add_b_ions", "true", "Add peaks of b-ions to the spectrum"); - defaults_.setValidStrings("add_b_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_b_ions", {"true","false"}); defaults_.setValue("add_c_ions", "false", "Add peaks of c-ions to the spectrum"); - defaults_.setValidStrings("add_c_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_c_ions", {"true","false"}); defaults_.setValue("add_d_ions", "false", "Add peaks of d-ions to the spectrum"); - defaults_.setValidStrings("add_d_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_d_ions", {"true","false"}); defaults_.setValue("add_w_ions", "false", "Add peaks of w-ions to the spectrum"); - defaults_.setValidStrings("add_w_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_w_ions", {"true","false"}); defaults_.setValue("add_x_ions", "false", "Add peaks of x-ions to the spectrum"); - defaults_.setValidStrings("add_x_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_x_ions", {"true","false"}); defaults_.setValue("add_y_ions", "true", "Add peaks of y-ions to the spectrum"); - defaults_.setValidStrings("add_y_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_y_ions", {"true","false"}); defaults_.setValue("add_z_ions", "false", "Add peaks of z-ions to the spectrum"); - defaults_.setValidStrings("add_z_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_z_ions", {"true","false"}); defaults_.setValue("add_a-B_ions", "false", "Add peaks of a-B-ions to the spectrum (nucleotide sequences only)"); - defaults_.setValidStrings("add_a-B_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_a-B_ions", {"true","false"}); // intensity options of the ions defaults_.setValue("a_intensity", 1.0, "Intensity of the a-ions"); diff --git a/src/openms/source/CHEMISTRY/SimpleTSGXLMS.cpp b/src/openms/source/CHEMISTRY/SimpleTSGXLMS.cpp index 2ad3ee47031..2d6c4114d46 100644 --- a/src/openms/source/CHEMISTRY/SimpleTSGXLMS.cpp +++ b/src/openms/source/CHEMISTRY/SimpleTSGXLMS.cpp @@ -52,44 +52,44 @@ namespace OpenMS { // TODO only partly functional (second isotopic peak if max_isotope = 2) defaults_.setValue("add_isotopes", "false", "If set to 1 isotope peaks of the product ion peaks are added"); - defaults_.setValidStrings("add_isotopes", ListUtils::create("true,false")); + defaults_.setValidStrings("add_isotopes", {"true","false"}); defaults_.setValue("max_isotope", 2, "Defines the maximal isotopic peak which is added, add_isotopes must be set to 1"); defaults_.setValue("add_losses", "false", "Adds common losses to those ion expect to have them, only water and ammonia loss is considered"); - defaults_.setValidStrings("add_losses", ListUtils::create("true,false")); + defaults_.setValidStrings("add_losses", {"true","false"}); defaults_.setValue("add_precursor_peaks", "true", "Adds peaks of the precursor to the spectrum, which happen to occur sometimes"); - defaults_.setValidStrings("add_precursor_peaks", ListUtils::create("true,false")); + defaults_.setValidStrings("add_precursor_peaks", {"true","false"}); // TODO not functional yet defaults_.setValue("add_abundant_immonium_ions", "false", "Add most abundant immonium ions"); - defaults_.setValidStrings("add_abundant_immonium_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_abundant_immonium_ions", {"true","false"}); defaults_.setValue("add_k_linked_ions", "true", "Add RES-Linked ions, which are specific to XLMS"); - defaults_.setValidStrings("add_k_linked_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_k_linked_ions", {"true","false"}); // TODO not functional yet defaults_.setValue("add_first_prefix_ion", "true", "If set to true e.g. b1 ions are added"); - defaults_.setValidStrings("add_first_prefix_ion", ListUtils::create("true,false")); + defaults_.setValidStrings("add_first_prefix_ion", {"true","false"}); defaults_.setValue("add_y_ions", "true", "Add peaks of y-ions to the spectrum"); - defaults_.setValidStrings("add_y_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_y_ions", {"true","false"}); defaults_.setValue("add_b_ions", "true", "Add peaks of b-ions to the spectrum"); - defaults_.setValidStrings("add_b_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_b_ions", {"true","false"}); defaults_.setValue("add_a_ions", "true", "Add peaks of a-ions to the spectrum"); - defaults_.setValidStrings("add_a_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_a_ions", {"true","false"}); defaults_.setValue("add_c_ions", "false", "Add peaks of c-ions to the spectrum"); - defaults_.setValidStrings("add_c_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_c_ions", {"true","false"}); defaults_.setValue("add_x_ions", "false", "Add peaks of x-ions to the spectrum"); - defaults_.setValidStrings("add_x_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_x_ions", {"true","false"}); defaults_.setValue("add_z_ions", "false", "Add peaks of z-ions to the spectrum"); - defaults_.setValidStrings("add_z_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_z_ions", {"true","false"}); defaultsToParam_(); diff --git a/src/openms/source/CHEMISTRY/SpectrumAnnotator.cpp b/src/openms/source/CHEMISTRY/SpectrumAnnotator.cpp index 117595ebcfc..3f05998c523 100644 --- a/src/openms/source/CHEMISTRY/SpectrumAnnotator.cpp +++ b/src/openms/source/CHEMISTRY/SpectrumAnnotator.cpp @@ -50,7 +50,7 @@ namespace OpenMS DefaultParamHandler("SpectrumAnnotator") { defaults_.setValue("basic_statistics", "true", "If set, meta values for peak_number, sum_intensity, matched_ion_number, matched_intensity are added"); - defaults_.setValidStrings("basic_statistics", ListUtils::create("true,false")); + defaults_.setValidStrings("basic_statistics", {"true","false"}); /** adds meta values peak_number sum_intensity @@ -58,24 +58,24 @@ namespace OpenMS matched_intensity */ defaults_.setValue("list_of_ions_matched", "true", "If set, meta values for matched_ions are added"); - defaults_.setValidStrings("list_of_ions_matched", ListUtils::create("true,false")); + defaults_.setValidStrings("list_of_ions_matched", {"true","false"}); /** adds meta values matched_ions */ defaults_.setValue("max_series", "true", "If set, meta values for max_series_type, max_series_size are added"); - defaults_.setValidStrings("max_series", ListUtils::create("true,false")); + defaults_.setValidStrings("max_series", {"true","false"}); /** adds meta values max_series_type max_series_size */ defaults_.setValue("S/N_statistics", "true", "If set to 1 isotope peaks of the product ion peaks are added"); - defaults_.setValidStrings("S/N_statistics", ListUtils::create("true,false")); + defaults_.setValidStrings("S/N_statistics", {"true","false"}); /** adds meta values sn_by_matched_intensity sn_by_median_intensity */ defaults_.setValue("precursor_statistics", "true", "If set, meta values for precursor_in_ms2 are added"); - defaults_.setValidStrings("precursor_statistics", ListUtils::create("true,false")); + defaults_.setValidStrings("precursor_statistics", {"true","false"}); /** adds meta values precursor_in_ms2 */ @@ -88,13 +88,13 @@ namespace OpenMS // TODO right now topN matched, but additional information would be gained if the topN would be assembled from NOT ONLY the matched (high intense peak not identified?) defaults_.setValue("fragmenterror_statistics", "true", "If set, meta values for median_fragment_error, IQR_fragment_error are added"); - defaults_.setValidStrings("fragmenterror_statistics", ListUtils::create("true,false")); + defaults_.setValidStrings("fragmenterror_statistics", {"true","false"}); /** adds meta values median_fragment_error IQR_fragment_error */ defaults_.setValue("terminal_series_match_ratio", "true", "If set, meta values for NTermIonCurrentRatio, CTermIonCurrentRatio are added"); - defaults_.setValidStrings("terminal_series_match_ratio", ListUtils::create("true,false")); + defaults_.setValidStrings("terminal_series_match_ratio", {"true","false"}); /** adds meta values NTermIonCurrentRatio CTermIonCurrentRatio @@ -395,7 +395,7 @@ namespace OpenMS //TODO add "FragmentArray"s Param sap = sa.getParameters(); - pi.setMetaValue("fragment_match_tolerance", sap.getValue("tolerance")); + pi.setMetaValue("fragment_match_tolerance", (double)sap.getValue("tolerance")); } } } diff --git a/src/openms/source/CHEMISTRY/SvmTheoreticalSpectrumGenerator.cpp b/src/openms/source/CHEMISTRY/SvmTheoreticalSpectrumGenerator.cpp index bb72d5fb4df..41eeea0ff0f 100644 --- a/src/openms/source/CHEMISTRY/SvmTheoreticalSpectrumGenerator.cpp +++ b/src/openms/source/CHEMISTRY/SvmTheoreticalSpectrumGenerator.cpp @@ -174,42 +174,42 @@ namespace OpenMS defaults_.setValue("model_file_name", "examples/simulation/SvmMSim.model", "Name of the probabilistic Model file"); defaults_.setValue("add_isotopes", "false", "If set to 1 isotope peaks of the product ion peaks are added"); - defaults_.setValidStrings("add_isotopes", ListUtils::create("true,false")); + defaults_.setValidStrings("add_isotopes", {"true","false"}); defaults_.setValue("max_isotope", 2, "Defines the maximal isotopic peak which is added, add_isotopes must be set to 1"); defaults_.setValue("add_metainfo", "false", "Adds the type of peaks as metainfo to the peaks, like y8+, [M-H2O+2H]++"); - defaults_.setValidStrings("add_metainfo", ListUtils::create("true,false")); + defaults_.setValidStrings("add_metainfo", {"true","false"}); defaults_.setValue("add_first_prefix_ion", "false", "If set to true e.g. b1 ions are added"); - defaults_.setValidStrings("add_first_prefix_ion", ListUtils::create("true,false")); + defaults_.setValidStrings("add_first_prefix_ion", {"true","false"}); defaults_.setValue("hide_y_ions", "false", "Add peaks of y-ions to the spectrum"); - defaults_.setValidStrings("hide_y_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("hide_y_ions", {"true","false"}); defaults_.setValue("hide_y2_ions", "false", "Add peaks of y-ions to the spectrum"); - defaults_.setValidStrings("hide_y2_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("hide_y2_ions", {"true","false"}); defaults_.setValue("hide_b_ions", "false", "Add peaks of b-ions to the spectrum"); - defaults_.setValidStrings("hide_b_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("hide_b_ions", {"true","false"}); defaults_.setValue("hide_b2_ions", "false", "Add peaks of b-ions to the spectrum"); - defaults_.setValidStrings("hide_b2_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("hide_b2_ions", {"true","false"}); defaults_.setValue("hide_a_ions", "false", "Add peaks of a-ions to the spectrum"); - defaults_.setValidStrings("hide_a_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("hide_a_ions", {"true","false"}); defaults_.setValue("hide_c_ions", "false", "Add peaks of c-ions to the spectrum"); - defaults_.setValidStrings("hide_c_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("hide_c_ions", {"true","false"}); defaults_.setValue("hide_x_ions", "false", "Add peaks of x-ions to the spectrum"); - defaults_.setValidStrings("hide_x_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("hide_x_ions", {"true","false"}); defaults_.setValue("hide_z_ions", "false", "Add peaks of z-ions to the spectrum"); - defaults_.setValidStrings("hide_z_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("hide_z_ions", {"true","false"}); defaults_.setValue("hide_losses", "false", "Adds common losses to those ion expect to have them, only water and ammonia loss is considered"); - defaults_.setValidStrings("hide_losses", ListUtils::create("true,false")); + defaults_.setValidStrings("hide_losses", {"true","false"}); // intensity options of the ions defaults_.setValue("y_intensity", 1.0, "Intensity of the y-ions"); @@ -516,7 +516,7 @@ namespace OpenMS void SvmTheoreticalSpectrumGenerator::load() { - String svm_info_file = param_.getValue("model_file_name"); + String svm_info_file = String(param_.getValue("model_file_name").toString()); if (!File::readable(svm_info_file)) // look in OPENMS_DATA_PATH { svm_info_file = File::find(svm_info_file); diff --git a/src/openms/source/CHEMISTRY/SvmTheoreticalSpectrumGeneratorTrainer.cpp b/src/openms/source/CHEMISTRY/SvmTheoreticalSpectrumGeneratorTrainer.cpp index ac47681ad6e..305a011fa54 100644 --- a/src/openms/source/CHEMISTRY/SvmTheoreticalSpectrumGeneratorTrainer.cpp +++ b/src/openms/source/CHEMISTRY/SvmTheoreticalSpectrumGeneratorTrainer.cpp @@ -50,7 +50,7 @@ namespace OpenMS DefaultParamHandler("SvmTheoreticalSpectrumGeneratorTrainer") { defaults_.setValue("write_training_files", "false", "If set to true no models are trained but files (__training.dat) are produced for the selected primary ion types. They can be used as input for LibSVM command line tools"); - defaults_.setValidStrings("write_training_files", ListUtils::create("true,false")); + defaults_.setValidStrings("write_training_files", {"true","false"}); defaults_.setValue("number_intensity_levels", 7, "The number of intensity bins (for secondary type models)"); defaults_.setValue("number_regions", 3, "The number of regions each spectrum is split to (for secondary type models)"); @@ -58,24 +58,24 @@ namespace OpenMS defaults_.setValue("peak_tolerance", 0.5, "The maximum mass error for a peak to the expected mass of some ion type"); defaults_.setValue("add_b_ions", "true", "Train simulator for b-ions"); - defaults_.setValidStrings("add_b_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_b_ions", {"true","false"}); defaults_.setValue("add_y_ions", "true", "Train simulator for y-ions"); - defaults_.setValidStrings("add_y_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_y_ions", {"true","false"}); defaults_.setValue("add_a_ions", "false", "Train simulator for a-ions"); - defaults_.setValidStrings("add_a_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_a_ions", {"true","false"}); defaults_.setValue("add_c_ions", "false", "Train simulator for c-ions"); - defaults_.setValidStrings("add_c_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_c_ions", {"true","false"}); defaults_.setValue("add_x_ions", "false", "Train simulator for x-ions"); - defaults_.setValidStrings("add_x_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_x_ions", {"true","false"}); defaults_.setValue("add_z_ions", "false", "Train simulator for z-ions"); - defaults_.setValidStrings("add_z_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_z_ions", {"true","false"}); defaults_.setValue("add_losses", "false", "Train simulator for neutral losses of H2O and NH3 for b-ions and y-ions"); - defaults_.setValidStrings("add_losses", ListUtils::create("true,false")); + defaults_.setValidStrings("add_losses", {"true","false"}); defaults_.setValue("add_b2_ions", "false", "Train simulator for doubly charged b-ions"); - defaults_.setValidStrings("add_b2_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_b2_ions", {"true","false"}); defaults_.setValue("add_y2_ions", "false", "Train simulator for double charged y-ions"); - defaults_.setValidStrings("add_y2_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_y2_ions", {"true","false"}); defaults_.setValue("svm:svc_type", 0, "Type of the SVC: 0=C_SVC 1=NU_SVC"); defaults_.setMinInt("svm:svc_type", 0); @@ -127,16 +127,16 @@ namespace OpenMS //defaults_.setMinInt("svm:cache_size",1); //defaults_.setValue("svm:shrinking", "true", "Perform shrinking"); - //defaults_.setValidStrings("svm:shrinking", ListUtils::create("true,false")); + //defaults_.setValidStrings("svm:shrinking", {"true","false"}); defaults_.setValue("svm:scaling", "true", "Apply scaling of feature values"); - defaults_.setValidStrings("svm:scaling", ListUtils::create("true,false")); + defaults_.setValidStrings("svm:scaling", {"true","false"}); defaults_.setValue("svm:scaling_lower", 0.0, "Lower bound for scaling"); defaults_.setValue("svm:scaling_upper", 1.0, "Upper bound for scaling"); defaults_.setValue("svm:svc:balancing", "true", "Use class balanced SVC training"); - defaults_.setValidStrings("svm:svc:balancing", ListUtils::create("true,false")); + defaults_.setValidStrings("svm:svc:balancing", {"true","false"}); defaults_.setSectionDescription("svm", "Parameters controlling SVM trainig behaviour. All parameter names are chosen as in the libSVM library. Please refer to libSVM documentation for explanation"); defaults_.setSectionDescription("svm:svc", "Parameters for svm - classification of missing/abundant"); @@ -146,10 +146,10 @@ namespace OpenMS defaults_.setMinInt("svm:n_fold", 1); defaults_.setValue("svm:grid", "false", "Perform grid search"); - defaults_.setValidStrings("svm:grid", ListUtils::create("true,false")); + defaults_.setValidStrings("svm:grid", {"true","false"}); defaults_.setValue("svm:additive_cv", "false", "Additive step size (if false multiplicative)"); - defaults_.setValidStrings("svm:additive_cv", ListUtils::create("true,false")); + defaults_.setValidStrings("svm:additive_cv", {"true","false"}); defaults_.setValue("svm:svc:degree_start", 1, "starting point of degree"); defaults_.setMinInt("svm:svc:degree_start", 1); @@ -248,47 +248,47 @@ namespace OpenMS std::vector ion_types; std::vector is_primary; - if (DataValue(param_.getValue("add_b_ions")).toBool()) + if (param_.getValue("add_b_ions").toBool()) { ion_types.push_back(IonType(Residue::BIon, EmpiricalFormula(), 1)); is_primary.push_back(true); } - if (DataValue(param_.getValue("add_y_ions")).toBool()) + if (param_.getValue("add_y_ions").toBool()) { ion_types.push_back(IonType(Residue::YIon, EmpiricalFormula(), 1)); is_primary.push_back(true); } - if (DataValue(param_.getValue("add_x_ions")).toBool()) + if (param_.getValue("add_x_ions").toBool()) { ion_types.push_back(IonType(Residue::XIon, EmpiricalFormula(), 1)); is_primary.push_back(false); secondary_types = true; } - if (DataValue(param_.getValue("add_a_ions")).toBool()) + if (param_.getValue("add_a_ions").toBool()) { ion_types.push_back(IonType(Residue::AIon, EmpiricalFormula(), 1)); is_primary.push_back(false); secondary_types = true; } - if (DataValue(param_.getValue("add_z_ions")).toBool()) + if (param_.getValue("add_z_ions").toBool()) { ion_types.push_back(IonType(Residue::ZIon, EmpiricalFormula(), 1)); is_primary.push_back(false); secondary_types = true; } - if (DataValue(param_.getValue("add_c_ions")).toBool()) + if (param_.getValue("add_c_ions").toBool()) { ion_types.push_back(IonType(Residue::CIon, EmpiricalFormula(), 1)); is_primary.push_back(false); secondary_types = true; } - if (DataValue(param_.getValue("add_losses")).toBool()) + if (param_.getValue("add_losses").toBool()) { EmpiricalFormula loss_ammonia("NH3"); EmpiricalFormula loss_water("H2O"); - if (DataValue(param_.getValue("add_b_ions")).toBool()) + if (param_.getValue("add_b_ions").toBool()) { ion_types.push_back(IonType(Residue::BIon, loss_ammonia, 1)); ion_types.push_back(IonType(Residue::BIon, loss_water, 1)); @@ -296,7 +296,7 @@ namespace OpenMS is_primary.push_back(false); secondary_types = true; } - if (DataValue(param_.getValue("add_y_ions")).toBool()) + if (param_.getValue("add_y_ions").toBool()) { ion_types.push_back(IonType(Residue::YIon, loss_ammonia, 1)); ion_types.push_back(IonType(Residue::YIon, loss_water, 1)); @@ -306,13 +306,13 @@ namespace OpenMS } } - if (DataValue(param_.getValue("add_y2_ions")).toBool()) + if (param_.getValue("add_y2_ions").toBool()) { ion_types.push_back(IonType(Residue::YIon, EmpiricalFormula(), 2)); is_primary.push_back(false); secondary_types = true; } - if (DataValue(param_.getValue("add_b2_ions")).toBool()) + if (param_.getValue("add_b2_ions").toBool()) { ion_types.push_back(IonType(Residue::BIon, EmpiricalFormula(), 2)); is_primary.push_back(false); diff --git a/src/openms/source/CHEMISTRY/TheoreticalSpectrumGenerator.cpp b/src/openms/source/CHEMISTRY/TheoreticalSpectrumGenerator.cpp index 320ec3dffbd..9f7a11e87cf 100644 --- a/src/openms/source/CHEMISTRY/TheoreticalSpectrumGenerator.cpp +++ b/src/openms/source/CHEMISTRY/TheoreticalSpectrumGenerator.cpp @@ -53,49 +53,49 @@ namespace OpenMS DefaultParamHandler("TheoreticalSpectrumGenerator") { defaults_.setValue("isotope_model", "none", "Model to use for isotopic peaks ('none' means no isotopic peaks are added, 'coarse' adds isotopic peaks in unit mass distance, 'fine' uses the hyperfine isotopic generator to add accurate isotopic peaks. Note that adding isotopic peaks is very slow."); - defaults_.setValidStrings("isotope_model", ListUtils::create("none,coarse,fine")); + defaults_.setValidStrings("isotope_model", {"none","coarse","fine"}); defaults_.setValue("max_isotope", 2, "Defines the maximal isotopic peak which is added if 'isotope_model' is 'coarse'"); defaults_.setValue("max_isotope_probability", 0.05, "Defines the maximal isotopic probability to cover if 'isotope_model' is 'fine'"); defaults_.setValue("add_metainfo", "false", "Adds the type of peaks as metainfo to the peaks, like y8+, [M-H2O+2H]++"); - defaults_.setValidStrings("add_metainfo", ListUtils::create("true,false")); + defaults_.setValidStrings("add_metainfo", {"true","false"}); defaults_.setValue("add_losses", "false", "Adds common losses to those ion expect to have them, only water and ammonia loss is considered"); - defaults_.setValidStrings("add_losses", ListUtils::create("true,false")); + defaults_.setValidStrings("add_losses", {"true","false"}); defaults_.setValue("sort_by_position", "true", "Sort output by position"); - defaults_.setValidStrings("sort_by_position", ListUtils::create("true,false")); + defaults_.setValidStrings("sort_by_position", {"true","false"}); defaults_.setValue("add_precursor_peaks", "false", "Adds peaks of the unfragmented precursor ion to the spectrum"); - defaults_.setValidStrings("add_precursor_peaks", ListUtils::create("true,false")); + defaults_.setValidStrings("add_precursor_peaks", {"true","false"}); defaults_.setValue("add_all_precursor_charges", "false", "Adds precursor peaks with all charges in the given range"); - defaults_.setValidStrings("add_all_precursor_charges", ListUtils::create("true,false")); + defaults_.setValidStrings("add_all_precursor_charges", {"true","false"}); defaults_.setValue("add_abundant_immonium_ions", "false", "Add most abundant immonium ions"); - defaults_.setValidStrings("add_abundant_immonium_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_abundant_immonium_ions", {"true","false"}); defaults_.setValue("add_first_prefix_ion", "false", "If set to true e.g. b1 ions are added"); - defaults_.setValidStrings("add_first_prefix_ion", ListUtils::create("true,false")); + defaults_.setValidStrings("add_first_prefix_ion", {"true","false"}); defaults_.setValue("add_y_ions", "true", "Add peaks of y-ions to the spectrum"); - defaults_.setValidStrings("add_y_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_y_ions", {"true","false"}); defaults_.setValue("add_b_ions", "true", "Add peaks of b-ions to the spectrum"); - defaults_.setValidStrings("add_b_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_b_ions", {"true","false"}); defaults_.setValue("add_a_ions", "false", "Add peaks of a-ions to the spectrum"); - defaults_.setValidStrings("add_a_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_a_ions", {"true","false"}); defaults_.setValue("add_c_ions", "false", "Add peaks of c-ions to the spectrum"); - defaults_.setValidStrings("add_c_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_c_ions", {"true","false"}); defaults_.setValue("add_x_ions", "false", "Add peaks of x-ions to the spectrum"); - defaults_.setValidStrings("add_x_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_x_ions", {"true","false"}); defaults_.setValue("add_z_ions", "false", "Add peaks of z-ions to the spectrum"); - defaults_.setValidStrings("add_z_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_z_ions", {"true","false"}); // intensity options of the ions defaults_.setValue("y_intensity", 1.0, "Intensity of the y-ions"); diff --git a/src/openms/source/CHEMISTRY/TheoreticalSpectrumGeneratorXLMS.cpp b/src/openms/source/CHEMISTRY/TheoreticalSpectrumGeneratorXLMS.cpp index fafee5a8fab..c743326804b 100644 --- a/src/openms/source/CHEMISTRY/TheoreticalSpectrumGeneratorXLMS.cpp +++ b/src/openms/source/CHEMISTRY/TheoreticalSpectrumGeneratorXLMS.cpp @@ -48,50 +48,50 @@ namespace OpenMS { // TODO only partly functional (second isotopic peak if max_isotope = 2) defaults_.setValue("add_isotopes", "false", "If set to 1 isotope peaks of the product ion peaks are added"); - defaults_.setValidStrings("add_isotopes", ListUtils::create("true,false")); + defaults_.setValidStrings("add_isotopes", {"true","false"}); defaults_.setValue("max_isotope", 2, "Defines the maximal isotopic peak which is added, add_isotopes must be set to 1"); defaults_.setValue("add_metainfo", "true", "Adds the type of peaks as metainfo to the peaks, like y8+, [M-H2O+2H]++"); - defaults_.setValidStrings("add_metainfo", ListUtils::create("true,false")); + defaults_.setValidStrings("add_metainfo", {"true","false"}); defaults_.setValue("add_charges", "true", "Adds the charges to a DataArray of the spectrum"); - defaults_.setValidStrings("add_charges", ListUtils::create("true,false")); + defaults_.setValidStrings("add_charges", {"true","false"}); defaults_.setValue("add_losses", "false", "Adds common losses to those ion expect to have them, only water and ammonia loss is considered"); - defaults_.setValidStrings("add_losses", ListUtils::create("true,false")); + defaults_.setValidStrings("add_losses", {"true","false"}); defaults_.setValue("add_precursor_peaks", "true", "Adds peaks of the precursor to the spectrum, which happen to occur sometimes"); - defaults_.setValidStrings("add_precursor_peaks", ListUtils::create("true,false")); + defaults_.setValidStrings("add_precursor_peaks", {"true","false"}); // TODO not functional yet defaults_.setValue("add_abundant_immonium_ions", "false", "Add most abundant immonium ions"); - defaults_.setValidStrings("add_abundant_immonium_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_abundant_immonium_ions", {"true","false"}); defaults_.setValue("add_k_linked_ions", "true", "Add RES-Linked ions, which are specific to XLMS"); - defaults_.setValidStrings("add_k_linked_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_k_linked_ions", {"true","false"}); // TODO not functional yet defaults_.setValue("add_first_prefix_ion", "true", "If set to true e.g. b1 ions are added"); - defaults_.setValidStrings("add_first_prefix_ion", ListUtils::create("true,false")); + defaults_.setValidStrings("add_first_prefix_ion", {"true","false"}); defaults_.setValue("add_y_ions", "true", "Add peaks of y-ions to the spectrum"); - defaults_.setValidStrings("add_y_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_y_ions", {"true","false"}); defaults_.setValue("add_b_ions", "true", "Add peaks of b-ions to the spectrum"); - defaults_.setValidStrings("add_b_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_b_ions", {"true","false"}); defaults_.setValue("add_a_ions", "true", "Add peaks of a-ions to the spectrum"); - defaults_.setValidStrings("add_a_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_a_ions", {"true","false"}); defaults_.setValue("add_c_ions", "false", "Add peaks of c-ions to the spectrum"); - defaults_.setValidStrings("add_c_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_c_ions", {"true","false"}); defaults_.setValue("add_x_ions", "false", "Add peaks of x-ions to the spectrum"); - defaults_.setValidStrings("add_x_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_x_ions", {"true","false"}); defaults_.setValue("add_z_ions", "false", "Add peaks of z-ions to the spectrum"); - defaults_.setValidStrings("add_z_ions", ListUtils::create("true,false")); + defaults_.setValidStrings("add_z_ions", {"true","false"}); // intensity options of the ions diff --git a/src/openms/source/COMPARISON/SPECTRA/SpectrumAlignment.cpp b/src/openms/source/COMPARISON/SPECTRA/SpectrumAlignment.cpp index d1afff1e052..857c64fb479 100644 --- a/src/openms/source/COMPARISON/SPECTRA/SpectrumAlignment.cpp +++ b/src/openms/source/COMPARISON/SPECTRA/SpectrumAlignment.cpp @@ -44,7 +44,7 @@ namespace OpenMS { defaults_.setValue("tolerance", 0.3, "Defines the absolute (in Da) or relative (in ppm) tolerance"); defaults_.setValue("is_relative_tolerance", "false", "If true, the 'tolerance' is interpreted as ppm-value"); - defaults_.setValidStrings("is_relative_tolerance", ListUtils::create("true,false")); + defaults_.setValidStrings("is_relative_tolerance", {"true","false"}); defaultsToParam_(); } diff --git a/src/openms/source/COMPARISON/SPECTRA/SpectrumAlignmentScore.cpp b/src/openms/source/COMPARISON/SPECTRA/SpectrumAlignmentScore.cpp index c91dd831ae1..67f82782f04 100644 --- a/src/openms/source/COMPARISON/SPECTRA/SpectrumAlignmentScore.cpp +++ b/src/openms/source/COMPARISON/SPECTRA/SpectrumAlignmentScore.cpp @@ -44,11 +44,11 @@ namespace OpenMS setName(SpectrumAlignmentScore::getProductName()); defaults_.setValue("tolerance", 0.3, "Defines the absolute (in Da) or relative (in ppm) tolerance"); defaults_.setValue("is_relative_tolerance", "false", "if true, the tolerance value is interpreted as ppm"); - defaults_.setValidStrings("is_relative_tolerance", ListUtils::create("true,false")); + defaults_.setValidStrings("is_relative_tolerance", {"true","false"}); defaults_.setValue("use_linear_factor", "false", "if true, the intensities are weighted with the relative m/z difference"); - defaults_.setValidStrings("use_linear_factor", ListUtils::create("true,false")); + defaults_.setValidStrings("use_linear_factor", {"true","false"}); defaults_.setValue("use_gaussian_factor", "false", "if true, the intensities are weighted with the relative m/z difference using a gaussian"); - defaults_.setValidStrings("use_gaussian_factor", ListUtils::create("true,false")); + defaults_.setValidStrings("use_gaussian_factor", {"true","false"}); defaultsToParam_(); } @@ -87,7 +87,7 @@ namespace OpenMS SpectrumAlignment aligner; Param p; p.setValue("tolerance", tolerance); - p.setValue("is_relative_tolerance", (String)param_.getValue("is_relative_tolerance")); + p.setValue("is_relative_tolerance", param_.getValue("is_relative_tolerance")); aligner.setParameters(p); vector> alignment; diff --git a/src/openms/source/COMPARISON/SPECTRA/ZhangSimilarityScore.cpp b/src/openms/source/COMPARISON/SPECTRA/ZhangSimilarityScore.cpp index c9de057c65c..9d55d45c662 100644 --- a/src/openms/source/COMPARISON/SPECTRA/ZhangSimilarityScore.cpp +++ b/src/openms/source/COMPARISON/SPECTRA/ZhangSimilarityScore.cpp @@ -49,11 +49,11 @@ namespace OpenMS setName(ZhangSimilarityScore::getProductName()); defaults_.setValue("tolerance", 0.2, "defines the absolute (in Da) or relative (in ppm) tolerance"); defaults_.setValue("is_relative_tolerance", "false", "If set to true, the tolerance is interpreted as relative"); - defaults_.setValidStrings("is_relative_tolerance", ListUtils::create("true,false")); + defaults_.setValidStrings("is_relative_tolerance", {"true","false"}); defaults_.setValue("use_linear_factor", "false", "if true, the intensities are weighted with the relative m/z difference"); - defaults_.setValidStrings("use_linear_factor", ListUtils::create("true,false")); + defaults_.setValidStrings("use_linear_factor", {"true","false"}); defaults_.setValue("use_gaussian_factor", "false", "if true, the intensities are weighted with the relative m/z difference using a gaussian"); - defaults_.setValidStrings("use_gaussian_factor", ListUtils::create("true,false")); + defaults_.setValidStrings("use_gaussian_factor", {"true","false"}); defaultsToParam_(); } diff --git a/src/openms/source/CONCEPT/Constants.cpp b/src/openms/source/CONCEPT/Constants.cpp deleted file mode 100644 index 5b8725d9583..00000000000 --- a/src/openms/source/CONCEPT/Constants.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// -------------------------------------------------------------------------- -// OpenMS -- Open-Source Mass Spectrometry -// -------------------------------------------------------------------------- -// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, -// ETH Zurich, and Freie Universitaet Berlin 2002-2020. -// -// This software is released under a three-clause BSD license: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of any author or any participating institution -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// For a full list of authors, refer to the file AUTHORS. -// -------------------------------------------------------------------------- -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING -// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// -------------------------------------------------------------------------- -// $Maintainer: Timo Sachsenberg$ -// $Authors: Marc Sturm $ -// -------------------------------------------------------------------------- - -#include - -namespace OpenMS -{ - namespace Constants - { - // EPSILON (used for comparisons) - double EPSILON = 1e-6; - - // PI - const double PI = 3.14159265358979323846; - - // Euler's number - base of the natural logarithm - const double E = 2.718281828459045235; - - // Elementary charge - const double ELEMENTARY_CHARGE = 1.60217738E-19; // C - - // Elementary charge (alias) - const double e0 = ELEMENTARY_CHARGE; - - // Electron mass - const double ELECTRON_MASS = 9.1093897E-31; // kg - - // Electron mass in units - const double ELECTRON_MASS_U = 1.0 / 1822.8885020477; // u - - // Proton mass - const double PROTON_MASS = 1.6726230E-27; // kg - - // Proton mass in units - const double PROTON_MASS_U = 1.0072764667710;// u - - // Mass difference between Carbon-13 and Carbon-12 in units - const double C13C12_MASSDIFF_U = 1.0033548378; // u - - // Neutron mass - const double NEUTRON_MASS = 1.6749286E-27; // kg - - // Neutron mass in units - const double NEUTRON_MASS_U = 1.00866491566; // u - - // Avogadro constant - const double AVOGADRO = 6.0221367E+23; // 1 / mol - - // Avogadro constant (alias) - const double NA = AVOGADRO; - - // Avogadro constant (alias) - const double MOL = AVOGADRO; - - // Boltzmann constant - const double BOLTZMANN = 1.380657E-23; // J / K - - // Boltzmann constant (alias) - const double k = BOLTZMANN; - - // Planck constant - const double PLANCK = 6.6260754E-34; // J * sec - - // Planck constant (alias) - const double h = PLANCK; - - // Gas constant (= NA * k) - const double GAS_CONSTANT = NA * k; - - // Gas constant (alias) - const double R = GAS_CONSTANT; - - // Faraday constant (= NA * e0) - const double FARADAY = NA * e0; - - // Faraday constant (alias) - const double F = FARADAY; - - // Bohr radius - const double BOHR_RADIUS = 5.29177249E-11; // m - - // Bohr radius (alias) - const double a0 = BOHR_RADIUS; - - // the following values from: - // P.W.Atkins: Physical Chemistry, 5th ed., Oxford University Press, 1995 - - // Vacuum permittivity - const double VACUUM_PERMITTIVITY = 8.85419E-12; // C^2 / (J * m) - - // Vacuum permeability - const double VACUUM_PERMEABILITY = (4 * PI * 1E-7); // J s^2 / (C^2 * m) - - // Speed of light - const double SPEED_OF_LIGHT = 2.99792458E+8; // m / s - - // Speed of Light (alias) - const double c = SPEED_OF_LIGHT; - - // Gravitational constant - const double GRAVITATIONAL_CONSTANT = 6.67259E-11; // N m^2 / kg^2 - - // Fine structure constant - const double FINE_STRUCTURE_CONSTANT = 7.29735E-3; // 1 - - // Degree per rad - const double DEG_PER_RAD = 57.2957795130823209; - - // Rad per degree - const double RAD_PER_DEG = 0.0174532925199432957; - - // mm per inch - const double MM_PER_INCH = 25.4; - - // m per foot - const double M_PER_FOOT = 3.048; - - // Joule per calorie - const double JOULE_PER_CAL = 4.184; - - // Calories per Joule - const double CAL_PER_JOULE = (1 / 4.184); - - namespace UserParam - { - //User parameter name for identifier of concatenated peptides - const std::string CONCAT_PEPTIDE = "concatenated_peptides"; - - // User parameter name for the M/Z of other chromatograms which have been merged into this one - const std::string MERGED_CHROMATOGRAM_MZS = "merged_chromatogram_mzs"; - - // User parameter name for precursor mz error in ppm - const std::string LOCALIZED_MODIFICATIONS_USERPARAM = "localized_modifications"; - - // User parameter name for precursor mz error in ppm - const std::string PRECURSOR_ERROR_PPM_USERPARAM = "precursor_mz_error_ppm"; - - // User parameter name for median of fragment mz error in ppm - const std::string FRAGMENT_ERROR_MEDIAN_PPM_USERPARAM = "fragment_mz_error_median_ppm"; - - // User metavalue name for fragment mz error in ppm - const std::string FRAGMENT_ERROR_PPM_USERPARAM = "fragment_mass_error_ppm"; - - // User metavalue name for fragment mz error in da - const std::string FRAGMENT_ERROR_DA_USERPARAM = "fragment_mass_error_da"; - - // User parameter name for precursor mz error in ppm - const std::string FRAGMENT_ANNOTATION_USERPARAM = "fragment_annotation"; - - // User parameter name for explained ion current of a psm - const std::string PSM_EXPLAINED_ION_CURRENT_USERPARAM = "PSM_explained_ion_current"; - - // User parameter name for the spectrum reference in PeptideIdentification (is is not yet treated as a class attribute) - const std::string SPECTRUM_REFERENCE = "spectrum_reference"; - - // User parameter name for target/decoy annotation of a PeptideHit, e.g. as annotated by PeptideIndexer. One of: target, decoy, target+decoy - const std::string TARGET_DECOY = "target_decoy"; - - // User parameter name for a delta score: a score ratio between a rank x hit and the rank x+1 hit - const std::string DELTA_SCORE = "delta_score"; - - // User parameter name for monoisotopic peak misassignment correction of a precursor (usually an integer x with the correction being -x times C13C12_MASSDIFF_U) - const std::string ISOTOPE_ERROR = "isotope_error"; - - // Cross-Linking Mass Spectrometry user parameters - // Name of OpenPepXL main score (MzIdentML CV term) - const std::string OPENPEPXL_SCORE = "OpenPepXL:score"; - - // User parameter name for the sequence of the second peptide in a cross-link - const std::string OPENPEPXL_BETA_SEQUENCE = "sequence_beta"; - - // User parameter name for the protein accessions of the second peptide in a cross-link - const std::string OPENPEPXL_BETA_ACCESSIONS = "accessions_beta"; - - // User parameter name for the 1st position of cross-link (alpha peptide position in a real cross-link, 1st of two positions in a loop-link, modified position in a mono-link) - const std::string OPENPEPXL_XL_POS1 = "xl_pos1"; - - // User parameter name for the 2nd position of cross-link (beta peptide position in a real cross-link, 2nd of two positions in a loop-link, "-" in a mono-link) - const std::string OPENPEPXL_XL_POS2 = "xl_pos2"; - - // User parameter name for the 1st cross-link position on the protein - const std::string OPENPEPXL_XL_POS1_PROT = "xl_pos1_protein"; - - // User parameter name for the 1st cross-link position on the protein - const std::string OPENPEPXL_XL_POS2_PROT = "xl_pos2_protein"; - - // User parameter name for the cross-link type, one of: cross-link, loop-link, mono-link - const std::string OPENPEPXL_XL_TYPE = "xl_type"; - - // User parameter name for the cross-link rank (ranks of PeptideHits across different PeptideIdentifications) - const std::string OPENPEPXL_XL_RANK = "xl_rank"; - - // User parameter name for the name of a cross-link - const std::string OPENPEPXL_XL_MOD = "xl_mod"; - - // User parameter name for the mass of a cross-link - const std::string OPENPEPXL_XL_MASS = "xl_mass"; - - // User parameter name for the terminal specificity of a cross-link on the alpha peptide (to distinguish a link to the first or last residue side chain from a terminal link) - const std::string OPENPEPXL_XL_TERM_SPEC_ALPHA = "xl_term_spec_alpha"; - - // User parameter name for the terminal specificity of a cross-link on the beta peptide (to distinguish a link to the first or last residue side chain from a terminal link) - const std::string OPENPEPXL_XL_TERM_SPEC_BETA = "xl_term_spec_beta"; - - // User parameter name for the RT of the heavy spectrum precursor in a labeled cross-linking experiment - const std::string OPENPEPXL_HEAVY_SPEC_RT = "spec_heavy_RT"; - - // User parameter name for the m/z of the heavy spectrum precursor in a labeled cross-linking experiment - const std::string OPENPEPXL_HEAVY_SPEC_MZ = "spec_heavy_MZ"; - - // User parameter name for the spectrum reference of the heavy spectrum in a labeled cross-linking experiment - const std::string OPENPEPXL_HEAVY_SPEC_REF = "spectrum_reference_heavy"; - - // User parameter name for target/decoy annotation of alpha peptides - const std::string OPENPEPXL_TARGET_DECOY_ALPHA = "xl_target_decoy_alpha"; - - // User parameter name for target/decoy annotation of beta peptides - const std::string OPENPEPXL_TARGET_DECOY_BETA = "xl_target_decoy_beta"; - - // User parameter name for PeptideEvidence info for the beta/acceptor peptide: pre - const std::string OPENPEPXL_BETA_PEPEV_PRE = "BetaPepEv:pre"; - - // User parameter name for PeptideEvidence info for the beta/acceptor peptide: post - const std::string OPENPEPXL_BETA_PEPEV_POST = "BetaPepEv:post"; - - // User parameter name for PeptideEvidence info for the beta/acceptor peptide: start - const std::string OPENPEPXL_BETA_PEPEV_START = "BetaPepEv:start"; - - // User parameter name for PeptideEvidence info for the beta/acceptor peptide: end - const std::string OPENPEPXL_BETA_PEPEV_END = "BetaPepEv:end"; - - // User parameter name for XL-MS FDR values - const std::string XFDR_FDR = "XFDR:FDR"; - } - } -} diff --git a/src/openms/source/CONCEPT/LogConfigHandler.cpp b/src/openms/source/CONCEPT/LogConfigHandler.cpp index 9487c93aa24..9e3fafccb4f 100644 --- a/src/openms/source/CONCEPT/LogConfigHandler.cpp +++ b/src/openms/source/CONCEPT/LogConfigHandler.cpp @@ -86,7 +86,7 @@ namespace OpenMS { Param p; String suffix = " FILE"; - StringList commands; + std::vector commands; for (StringList::const_iterator iter = settings.begin(); iter != settings.end(); ++iter) { // split by " " to get all keywords @@ -112,7 +112,7 @@ namespace OpenMS void LogConfigHandler::configure(const Param & param) { - StringList configurations = param.getValue(LogConfigHandler::PARAM_NAME); + StringList configurations = ListUtils::toStringList(param.getValue(LogConfigHandler::PARAM_NAME)); for (StringList::const_iterator iter = configurations.begin(); iter != configurations.end(); ++iter) { diff --git a/src/openms/source/CONCEPT/sources.cmake b/src/openms/source/CONCEPT/sources.cmake index 01e72762e89..d8e51113075 100644 --- a/src/openms/source/CONCEPT/sources.cmake +++ b/src/openms/source/CONCEPT/sources.cmake @@ -4,7 +4,6 @@ set(directory source/CONCEPT) ### list all filenames of the directory here set(sources_list ClassTest.cpp -Constants.cpp Exception.cpp FuzzyStringComparator.cpp GlobalExceptionHandler.cpp diff --git a/src/openms/source/DATASTRUCTURES/DataValue.cpp b/src/openms/source/DATASTRUCTURES/DataValue.cpp index d3e24dc47a1..03bedf908e3 100644 --- a/src/openms/source/DATASTRUCTURES/DataValue.cpp +++ b/src/openms/source/DATASTRUCTURES/DataValue.cpp @@ -34,8 +34,8 @@ #include -#include #include +#include #include @@ -173,6 +173,41 @@ namespace OpenMS data_.dou_list_ = new DoubleList(p); } + DataValue::DataValue(const ParamValue& p) : + unit_type_(OTHER), unit_(-1) + { + switch (p.valueType()) + { + case ParamValue::EMPTY_VALUE: + value_type_ = EMPTY_VALUE; + break; + case ParamValue::INT_VALUE: + value_type_ = INT_VALUE; + data_.ssize_ = p; + break; + case ParamValue::DOUBLE_VALUE: + value_type_ = DOUBLE_VALUE; + data_.dou_ = p; + break; + case ParamValue::STRING_VALUE: + value_type_ = STRING_VALUE; + data_.str_ = new String(p.toChar()); + break; + case ParamValue::INT_LIST: + value_type_ = INT_LIST; + data_.int_list_ = new IntList(p.toIntVector()); + break; + case ParamValue::DOUBLE_LIST: + value_type_ = DOUBLE_LIST; + data_.dou_list_ = new DoubleList(p.toDoubleVector()); + break; + case ParamValue::STRING_LIST: + value_type_ = STRING_LIST; + data_.str_list_ = new StringList(ListUtils::toStringList(p)); + break; + } + } + //-------------------------------------------------------------------- // copy and move constructors //-------------------------------------------------------------------- diff --git a/src/openms/source/DATASTRUCTURES/DefaultParamHandler.cpp b/src/openms/source/DATASTRUCTURES/DefaultParamHandler.cpp index ac93ec3f48a..3880475fb0f 100644 --- a/src/openms/source/DATASTRUCTURES/DefaultParamHandler.cpp +++ b/src/openms/source/DATASTRUCTURES/DefaultParamHandler.cpp @@ -184,7 +184,7 @@ namespace OpenMS } for (auto it = write_this.begin(); it != write_this.end(); it++) { - write_here.setMetaValue(prefix_ + (*it).name, (*it).value); + write_here.setMetaValue(prefix_ + (*it).name, DataValue((*it).value)); } } diff --git a/src/openms/source/DATASTRUCTURES/Param.cpp b/src/openms/source/DATASTRUCTURES/Param.cpp index c058e60f66a..d662c28f41c 100644 --- a/src/openms/source/DATASTRUCTURES/Param.cpp +++ b/src/openms/source/DATASTRUCTURES/Param.cpp @@ -36,12 +36,6 @@ #include -#include -#include - -#include -#include - namespace OpenMS { @@ -53,30 +47,30 @@ namespace OpenMS tags(), min_float(-std::numeric_limits::max()), max_float(std::numeric_limits::max()), - min_int(-std::numeric_limits::max()), - max_int(std::numeric_limits::max()), + min_int(-std::numeric_limits::max()), + max_int(std::numeric_limits::max()), valid_strings() { } - Param::ParamEntry::ParamEntry(const String& n, const DataValue& v, const String& d, const StringList& t) : + Param::ParamEntry::ParamEntry(const std::string& n, const ParamValue& v, const std::string& d, const std::vector& t) : name(n), description(d), value(v), tags(), min_float(-std::numeric_limits::max()), max_float(std::numeric_limits::max()), - min_int(-std::numeric_limits::max()), - max_int(std::numeric_limits::max()), + min_int(-std::numeric_limits::max()), + max_int(std::numeric_limits::max()), valid_strings() { //add tags - for (Size i = 0; i < t.size(); ++i) + for (size_t i = 0; i < t.size(); ++i) { tags.insert(t[i]); } //check name - if (name.has(':')) + if (name.find(':') != std::string::npos) { std::cerr << "Error ParamEntry name must not contain ':' characters!" << std::endl; } @@ -86,9 +80,9 @@ namespace OpenMS { } - bool Param::ParamEntry::isValid(String& message) const + bool Param::ParamEntry::isValid(std::string& message) const { - if (value.valueType() == DataValue::STRING_VALUE) + if (value.valueType() == ParamValue::STRING_VALUE) { if (valid_strings.size() != 0) { @@ -105,18 +99,20 @@ namespace OpenMS if (!ok) { - String valid; - valid.concatenate(valid_strings.begin(), valid_strings.end(), ","); - message = "Invalid string parameter value '" + static_cast(value) + "' for parameter '" + name + "' given! Valid values are: '" + valid + "'."; + std::string valid = valid_strings.front(); + for (auto it = valid_strings.begin() + 1, end = valid_strings.end(); it != end; ++it) { + valid += "," + *it; + } + message = "Invalid string parameter value '" + value.toString() + "' for parameter '" + name + "' given! Valid values are: '" + valid + "'."; return false; } } } - else if (value.valueType() == DataValue::STRING_LIST) + else if (value.valueType() == ParamValue::STRING_LIST) { - String str_value; - StringList ls_value = value; - for (Size i = 0; i < ls_value.size(); ++i) + std::string str_value; + std::vector ls_value = value; + for (size_t i = 0; i < ls_value.size(); ++i) { str_value = ls_value[i]; @@ -135,55 +131,57 @@ namespace OpenMS if (!ok) { - String valid; - valid.concatenate(valid_strings.begin(), valid_strings.end(), ","); + std::string valid = valid_strings.front(); + for (auto it = valid_strings.begin() + 1, end = valid_strings.end(); it != end; ++it) { + valid += "," + *it; + } message = "Invalid string parameter value '" + str_value + "' for parameter '" + name + "' given! Valid values are: '" + valid + "'."; return false; } } } } - else if (value.valueType() == DataValue::INT_VALUE) + else if (value.valueType() == ParamValue::INT_VALUE) { - Int tmp = value; - if ((min_int != -std::numeric_limits::max() && tmp < min_int) || (max_int != std::numeric_limits::max() && tmp > max_int)) + int tmp = value; + if ((min_int != -std::numeric_limits::max() && tmp < min_int) || (max_int != std::numeric_limits::max() && tmp > max_int)) { - message = String("Invalid integer parameter value '") + String(tmp) + "' for parameter '" + name + "' given! The valid range is: [" + min_int + ":" + max_int + "]."; + message = "Invalid integer parameter value '" + std::to_string(tmp) + "' for parameter '" + name + "' given! The valid range is: [" + std::to_string(min_int) + ":" + std::to_string(max_int) + "]."; return false; } } - else if (value.valueType() == DataValue::INT_LIST) + else if (value.valueType() == ParamValue::INT_LIST) { - Int int_value; - IntList ls_value = value; - for (Size i = 0; i < ls_value.size(); ++i) + int int_value; + std::vector ls_value = value; + for (size_t i = 0; i < ls_value.size(); ++i) { int_value = ls_value[i]; - if ((min_int != -std::numeric_limits::max() && int_value < min_int) || (max_int != std::numeric_limits::max() && int_value > max_int)) + if ((min_int != -std::numeric_limits::max() && int_value < min_int) || (max_int != std::numeric_limits::max() && int_value > max_int)) { - message = String("Invalid integer parameter value '") + int_value + "' for parameter '" + name + "' given! The valid range is: [" + min_int + ":" + max_int + "]."; + message = "Invalid integer parameter value '" + std::to_string(int_value) + "' for parameter '" + name + "' given! The valid range is: [" + std::to_string(min_int) + ":" + std::to_string(max_int) + "]."; return false; } } } - else if (value.valueType() == DataValue::DOUBLE_VALUE) + else if (value.valueType() == ParamValue::DOUBLE_VALUE) { double tmp = value; if ((min_float != -std::numeric_limits::max() && tmp < min_float) || (max_float != std::numeric_limits::max() && tmp > max_float)) { - message = String("Invalid double parameter value '") + tmp + "' for parameter '" + name + "' given! The valid range is: [" + min_float + ":" + max_float + "]."; + message = "Invalid double parameter value '" + std::to_string(tmp) + "' for parameter '" + name + "' given! The valid range is: [" + std::to_string(min_float)+ ":" + std::to_string(max_float) + "]."; return false; } } - else if (value.valueType() == DataValue::DOUBLE_LIST) + else if (value.valueType() == ParamValue::DOUBLE_LIST) { - DoubleList ls_value = value; - for (Size i = 0; i < ls_value.size(); ++i) + std::vector ls_value = value; + for (size_t i = 0; i < ls_value.size(); ++i) { double dou_value = ls_value[i]; if ((min_float != -std::numeric_limits::max() && dou_value < min_float) || (max_float != std::numeric_limits::max() && dou_value > max_float)) { - message = String("Invalid double parameter value '") + dou_value + "' for parameter '" + name + "' given! The valid range is: [" + min_float + ":" + max_float + "]."; + message = "Invalid double parameter value '" + std::to_string(dou_value) + "' for parameter '" + name + "' given! The valid range is: [" + std::to_string(min_float) + ":" + std::to_string(max_float) + "]."; return false; } } @@ -205,16 +203,16 @@ namespace OpenMS { } - Param::ParamNode::ParamNode(const String& n, const String& d) : + Param::ParamNode::ParamNode(const std::string& n, const std::string& d) : name(n), description(d), entries(), nodes() { - if (name.has(':')) - { - std::cerr << "Error ParamNode name must not contain ':' characters!" << std::endl; - } + if (name.find(':') != std::string::npos) + { + std::cerr << "Error ParamNode name must not contain ':' characters!" << std::endl; + } } Param::ParamNode::~ParamNode() @@ -227,14 +225,14 @@ namespace OpenMS return false; //order of sections / entries should not matter - for (Size i = 0; i < entries.size(); ++i) + for (size_t i = 0; i < entries.size(); ++i) { if (find(rhs.entries.begin(), rhs.entries.end(), entries[i]) == rhs.entries.end()) { return false; } } - for (Size i = 0; i < nodes.size(); ++i) + for (size_t i = 0; i < nodes.size(); ++i) { if (find(rhs.nodes.begin(), rhs.nodes.end(), nodes[i]) == rhs.nodes.end()) { @@ -245,7 +243,7 @@ namespace OpenMS return true; } - Param::ParamNode::EntryIterator Param::ParamNode::findEntry(const String& local_name) + Param::ParamNode::EntryIterator Param::ParamNode::findEntry(const std::string& local_name) { for (EntryIterator it = entries.begin(); it != entries.end(); ++it) { @@ -257,7 +255,7 @@ namespace OpenMS return entries.end(); } - Param::ParamNode::NodeIterator Param::ParamNode::findNode(const String& local_name) + Param::ParamNode::NodeIterator Param::ParamNode::findNode(const std::string& local_name) { for (NodeIterator it = nodes.begin(); it != nodes.end(); ++it) { @@ -269,41 +267,43 @@ namespace OpenMS return nodes.end(); } - Param::ParamNode* Param::ParamNode::findParentOf(const String& local_name) + Param::ParamNode* Param::ParamNode::findParentOf(const std::string& local_name) { //cout << "findParentOf nodename: " << this->name << " - nodes: " << this->nodes.size() << " - find: "<< name << std::endl; - if (!local_name.has(':')) // we are in the right child + if (local_name.find(':') != std::string::npos) //several subnodes to browse through { - //check if a node or entry prefix match - for (Size i = 0; i < nodes.size(); ++i) - { - if (nodes[i].name.hasPrefix(local_name)) - return this; - } - for (Size i = 0; i < entries.size(); ++i) - { - if (entries[i].name.hasPrefix(local_name)) - return this; - } - return nullptr; + size_t pos = local_name.find(':'); + std::string prefix = local_name.substr(0, pos); + + //cout << " - Prefix: '" << prefix << "'" << std::endl; + NodeIterator it = findNode(prefix); + if (it == nodes.end()) //subnode not found + { + return nullptr; + } + //recursively call findNode for the rest of the path + std::string new_name = local_name.substr(it->name.size() + 1); + //cout << " - Next name: '" << new_name << "'" << std::endl; + return it->findParentOf(new_name); } - else //several subnodes to browse through + else // we are in the right child { - String prefix = local_name.prefix(':'); - //cout << " - Prefix: '" << prefix << "'" << std::endl; - NodeIterator it = findNode(prefix); - if (it == nodes.end()) //subnode not found - { + //check if a node or entry prefix match + for (size_t i = 0; i < nodes.size(); ++i) + { + if (nodes[i].name.compare(0, local_name.size(), local_name) == 0) + return this; + } + for (size_t i = 0; i < entries.size(); ++i) + { + if (entries[i].name.compare(0, local_name.size(), local_name) == 0) + return this; + } return nullptr; - } - //recursively call findNode for the rest of the path - String new_name = local_name.substr(it->name.size() + 1); - //cout << " - Next name: '" << new_name << "'" << std::endl; - return it->findParentOf(new_name); } } - Param::ParamEntry* Param::ParamNode::findEntryRecursive(const String& local_name) + Param::ParamEntry* Param::ParamNode::findEntryRecursive(const std::string& local_name) { ParamNode* parent = findParentOf(local_name); if (parent == nullptr) @@ -316,15 +316,16 @@ namespace OpenMS return &(*it); } - void Param::ParamNode::insert(const ParamNode& node, const String& prefix) + void Param::ParamNode::insert(const ParamNode& node, const std::string& prefix) { //std::cerr << "INSERT NODE " << node.name << " (" << prefix << ")" << std::endl; - String prefix2 = prefix + node.name; + std::string prefix2 = prefix + node.name; ParamNode* insert_node = this; - while (prefix2.has(':')) + while (prefix2.find(':') != std::string::npos) { - String local_name = prefix2.prefix(':'); + size_t pos = prefix2.find(':'); + std::string local_name = prefix2.substr(0, pos); //check if the node already exists NodeIterator it = insert_node->findNode(local_name); if (it != insert_node->nodes.end()) //exists @@ -366,16 +367,17 @@ namespace OpenMS } } - void Param::ParamNode::insert(const ParamEntry& entry, const String& prefix) + void Param::ParamNode::insert(const ParamEntry& entry, const std::string& prefix) { //std::cerr << "INSERT ENTRY " << entry.name << " (" << prefix << ")" << std::endl; - String prefix2 = prefix + entry.name; + std::string prefix2 = prefix + entry.name; //std::cerr << " - inserting: " << prefix2 << std::endl; ParamNode* insert_node = this; - while (prefix2.has(':')) + while (prefix2.find(':') != std::string::npos) { - String local_name = prefix2.prefix(':'); + size_t pos = prefix2.find(':'); + std::string local_name = prefix2.substr(0, pos); //std::cerr << " - looking for node: " << name << std::endl; //look up if the node already exists NodeIterator it = insert_node->findNode(local_name); @@ -414,9 +416,9 @@ namespace OpenMS } } - Size Param::ParamNode::size() const + size_t Param::ParamNode::size() const { - Size subnode_size = 0; + size_t subnode_size = 0; for (std::vector::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { subnode_size += it->size(); @@ -424,11 +426,12 @@ namespace OpenMS return entries.size() + subnode_size; } - String Param::ParamNode::suffix(const String& key) const + std::string Param::ParamNode::suffix(const std::string& key) const { - if (key.has(':')) + size_t pos = key.rfind(':'); + if (pos != std::string::npos) { - return key.suffix(':'); + return key.substr(++pos); } return key; } @@ -456,23 +459,23 @@ namespace OpenMS return root_ == rhs.root_; } - void Param::setValue(const String& key, const DataValue& value, const String& description, const StringList& tags) + void Param::setValue(const std::string& key, const ParamValue& value, const std::string& description, const std::vector& tags) { root_.insert(ParamEntry("", value, description, tags), key); } - void Param::setValidStrings(const String& key, const std::vector& strings) + void Param::setValidStrings(const std::string& key, const std::vector& strings) { ParamEntry& entry = getEntry_(key); //check if correct parameter type - if (entry.value.valueType() != DataValue::STRING_VALUE && entry.value.valueType() != DataValue::STRING_LIST) + if (entry.value.valueType() != ParamValue::STRING_VALUE && entry.value.valueType() != ParamValue::STRING_LIST) { throw Exception::ElementNotFound(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, key); } //check for commas - for (Size i = 0; i < strings.size(); ++i) + for (size_t i = 0; i < strings.size(); ++i) { - if (strings[i].has(',')) + if (strings[i].find(',') != std::string::npos) { throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Comma characters in Param string restrictions are not allowed!"); } @@ -480,56 +483,56 @@ namespace OpenMS entry.valid_strings = strings; } - void Param::setMinInt(const String& key, Int min) + void Param::setMinInt(const std::string& key, int min) { ParamEntry& entry = getEntry_(key); - if (entry.value.valueType() != DataValue::INT_VALUE && entry.value.valueType() != DataValue::INT_LIST) + if (entry.value.valueType() != ParamValue::INT_VALUE && entry.value.valueType() != ParamValue::INT_LIST) { throw Exception::ElementNotFound(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, key); } entry.min_int = min; } - void Param::setMaxInt(const String& key, Int max) + void Param::setMaxInt(const std::string& key, int max) { ParamEntry& entry = getEntry_(key); - if (entry.value.valueType() != DataValue::INT_VALUE && entry.value.valueType() != DataValue::INT_LIST) + if (entry.value.valueType() != ParamValue::INT_VALUE && entry.value.valueType() != ParamValue::INT_LIST) { throw Exception::ElementNotFound(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, key); } entry.max_int = max; } - void Param::setMinFloat(const String& key, double min) + void Param::setMinFloat(const std::string& key, double min) { ParamEntry& entry = getEntry_(key); - if (entry.value.valueType() != DataValue::DOUBLE_VALUE && entry.value.valueType() != DataValue::DOUBLE_LIST) + if (entry.value.valueType() != ParamValue::DOUBLE_VALUE && entry.value.valueType() != ParamValue::DOUBLE_LIST) { throw Exception::ElementNotFound(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, key); } entry.min_float = min; } - void Param::setMaxFloat(const String& key, double max) + void Param::setMaxFloat(const std::string& key, double max) { ParamEntry& entry = getEntry_(key); - if (entry.value.valueType() != DataValue::DOUBLE_VALUE && entry.value.valueType() != DataValue::DOUBLE_LIST) + if (entry.value.valueType() != ParamValue::DOUBLE_VALUE && entry.value.valueType() != ParamValue::DOUBLE_LIST) { throw Exception::ElementNotFound(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, key); } entry.max_float = max; } - const DataValue& Param::getValue(const String& key) const + const ParamValue& Param::getValue(const std::string& key) const { return getEntry_(key).value; } - const String& Param::getSectionDescription(const String& key) const + const std::string& Param::getSectionDescription(const std::string& key) const { //This variable is used instead of String::EMPTY as the method is used in //static initialization and thus cannot rely on String::EMPTY been initialized. - static String empty; + static std::string empty; ParamNode* node = root_.findParentOf(key); if (node == nullptr) @@ -546,7 +549,7 @@ namespace OpenMS return it->description; } - void Param::insert(const String& prefix, const Param& param) + void Param::insert(const std::string& prefix, const Param& param) { //std::cerr << "INSERT PARAM (" << prefix << ")" << std::endl; for (Param::ParamNode::NodeIterator it = param.root_.nodes.begin(); it != param.root_.nodes.end(); ++it) @@ -559,39 +562,42 @@ namespace OpenMS } } - void Param::setDefaults(const Param& defaults, const String& prefix, bool showMessage) + void Param::setDefaults(const Param& defaults, const std::string& prefix, bool showMessage) { - String prefix2 = prefix; + std::string prefix2 = prefix; if (prefix2 != "") { - prefix2.ensureLastChar(':'); + if (prefix2.back() != ':') + { + prefix2 += ':'; + } } - String pathname; + std::string pathname; for (Param::ParamIterator it = defaults.begin(); it != defaults.end(); ++it) { if (!exists(prefix2 + it.getName())) { if (showMessage) std::cerr << "Setting " << prefix2 + it.getName() << " to " << it->value << std::endl; - String name = prefix2 + it.getName(); + std::string name = prefix2 + it.getName(); root_.insert(ParamEntry("", it->value, it->description), name); //copy tags - for (std::set::const_iterator tag_it = it->tags.begin(); tag_it != it->tags.end(); ++tag_it) + for (std::set::const_iterator tag_it = it->tags.begin(); tag_it != it->tags.end(); ++tag_it) { addTag(name, *tag_it); } //copy restrictions - if (it->value.valueType() == DataValue::STRING_VALUE || it->value.valueType() == DataValue::STRING_LIST) + if (it->value.valueType() == ParamValue::STRING_VALUE || it->value.valueType() == ParamValue::STRING_LIST) { setValidStrings(name, it->valid_strings); } - else if (it->value.valueType() == DataValue::INT_VALUE || it->value.valueType() == DataValue::INT_LIST) + else if (it->value.valueType() == ParamValue::INT_VALUE || it->value.valueType() == ParamValue::INT_LIST) { setMinInt(name, it->min_int); setMaxInt(name, it->max_int); } - else if (it->value.valueType() == DataValue::DOUBLE_VALUE || it->value.valueType() == DataValue::DOUBLE_LIST) + else if (it->value.valueType() == ParamValue::DOUBLE_VALUE || it->value.valueType() == ParamValue::DOUBLE_LIST) { setMinFloat(name, it->min_float); setMaxFloat(name, it->max_float); @@ -610,11 +616,11 @@ namespace OpenMS { pathname.resize(pathname.size() - it2->name.size() - 1); } - String real_pathname = pathname.chop(1); //remove ':' at the end + std::string real_pathname = pathname.substr(0, pathname.length() - 1); //remove ':' at the end if (real_pathname != "") { - String description_old = getSectionDescription(prefix + real_pathname); - String description_new = defaults.getSectionDescription(real_pathname); + std::string description_old = getSectionDescription(prefix + real_pathname); + std::string description_new = defaults.getSectionDescription(real_pathname); if (description_old == "") { //std::cerr << "## Setting description of " << prefix+real_pathname << " to"<< std::endl; @@ -626,12 +632,12 @@ namespace OpenMS } } - void Param::remove(const String& key) + void Param::remove(const std::string& key) { - String keyname = key; - if (key.hasSuffix(':')) // delete section + std::string keyname = key; + if (!key.empty() && key.back() == ':') // delete section { - keyname = key.chop(1); + keyname = key.substr(0, key.length() - 1); ParamNode* node_parent = root_.findParentOf(keyname); if (node_parent != nullptr) @@ -639,12 +645,12 @@ namespace OpenMS Param::ParamNode::NodeIterator it = node_parent->findNode(node_parent->suffix(keyname)); if (it != node_parent->nodes.end()) { - String name = it->name; + std::string name = it->name; node_parent->nodes.erase(it); // will automatically delete subnodes if (node_parent->nodes.empty() && node_parent->entries.empty()) { // delete last section name (could be partial) - remove(keyname.chop(name.size())); // keep last ':' to indicate deletion of a section + remove(keyname.substr(0, keyname.size() - name.size())); // keep last ':' to indicate deletion of a section } } } @@ -654,7 +660,7 @@ namespace OpenMS ParamNode* node = root_.findParentOf(keyname); if (node != nullptr) { - String entryname = node->suffix(keyname); // get everything beyond last ':' + std::string entryname = node->suffix(keyname); // get everything beyond last ':' Param::ParamNode::EntryIterator it = node->findEntry(entryname); if (it != node->entries.end()) { @@ -662,29 +668,29 @@ namespace OpenMS if (node->nodes.empty() && node->entries.empty()) { // delete if section is now empty - remove(keyname.chop(entryname.size())); // keep last ':' to indicate deletion of a section + remove(keyname.substr(0, keyname.length() - entryname.length())); // keep last ':' to indicate deletion of a section } } } } } - void Param::removeAll(const String& prefix) + void Param::removeAll(const std::string& prefix) { - if (prefix.hasSuffix(':')) //we have to delete one node only (and its subnodes) + if (!prefix.empty() && prefix.back() == ':')//we have to delete one node only (and its subnodes) { - ParamNode* node = root_.findParentOf(prefix.chop(1)); + ParamNode* node = root_.findParentOf(prefix.substr(0, prefix.length() - 1)); if (node != nullptr) { - Param::ParamNode::NodeIterator it = node->findNode(node->suffix(prefix.chop(1))); + Param::ParamNode::NodeIterator it = node->findNode(node->suffix(prefix.substr(0, prefix.length() - 1))); if (it != node->nodes.end()) { - String name = it->name; + std::string name = it->name; node->nodes.erase(it); // will automatically delete subnodes if (node->nodes.empty() && node->entries.empty()) { // delete last section name (could be partial) - removeAll(prefix.chop(name.size() + 1)); // '+1' for the tailing ':' + removeAll(prefix.substr(0, prefix.length() - name.length() - 1));// '-1' for the tailing ':' } } } @@ -694,11 +700,11 @@ namespace OpenMS ParamNode* node = root_.findParentOf(prefix); if (node != nullptr) { - String suffix = node->suffix(prefix); // name behind last ":" + std::string suffix = node->suffix(prefix); // name behind last ":" for (Param::ParamNode::NodeIterator it = node->nodes.begin(); it != node->nodes.end(); /*do nothing*/) { - if (it->name.hasPrefix(suffix)) + if (it->name.compare(0, suffix.length(), suffix) == 0) { it = node->nodes.erase(it); } @@ -709,7 +715,7 @@ namespace OpenMS } for (Param::ParamNode::EntryIterator it = node->entries.begin(); it != node->entries.end(); /*do nothing*/) { - if (it->name.hasPrefix(suffix)) + if (it->name.compare(0, suffix.size(), suffix) == 0) { it = node->entries.erase(it); } @@ -722,7 +728,7 @@ namespace OpenMS if (node->nodes.empty() && node->entries.empty()) { // delete last section name (could be partial) - removeAll(prefix.chop(suffix.size())); + removeAll(prefix.substr(0, prefix.size() - suffix.size())); } } } @@ -760,7 +766,7 @@ namespace OpenMS return Param(out); } - Param Param::copy(const String& prefix, bool remove_prefix) const + Param Param::copy(const std::string& prefix, bool remove_prefix) const { ParamNode out("ROOT", ""); @@ -770,7 +776,7 @@ namespace OpenMS return Param(); } //we have to copy this node only - if (prefix.hasSuffix(':')) + if (!prefix.empty() && prefix.back() == ':') { if (remove_prefix) { @@ -778,15 +784,15 @@ namespace OpenMS } else { - out.insert(*node, prefix.chop(node->name.size() + 1)); + out.insert(*node, prefix.substr(0, prefix.size() - node->name.size() - 1)); } } else //we have to copy all entries and nodes starting with the right suffix { - String suffix = node->suffix(prefix); + std::string suffix = node->suffix(prefix); for (Param::ParamNode::NodeIterator it = node->nodes.begin(); it != node->nodes.end(); ++it) { - if (it->name.hasPrefix(suffix)) + if (it->name.compare(0, suffix.size(), suffix) == 0) { if (remove_prefix) { @@ -796,13 +802,13 @@ namespace OpenMS } else { - out.insert(*it, prefix.chop(suffix.size())); + out.insert(*it, prefix.substr(0, prefix.size() - suffix.size())); } } } for (Param::ParamNode::EntryIterator it = node->entries.begin(); it != node->entries.end(); ++it) { - if (it->name.hasPrefix(suffix)) + if (it->name.compare(0, suffix.size(), suffix) == 0) { if (remove_prefix) { @@ -812,7 +818,7 @@ namespace OpenMS } else { - out.insert(*it, prefix.chop(suffix.size())); + out.insert(*it, prefix.substr(0, prefix.size() - suffix.size())); } } } @@ -821,17 +827,21 @@ namespace OpenMS return Param(out); } - void Param::parseCommandLine(const int argc, const char** argv, const String& prefix) + void Param::parseCommandLine(const int argc, const char** argv, const std::string& prefix) { //determine prefix - String prefix2 = prefix; + std::string prefix2 = prefix; if (prefix2 != "") { - prefix2.ensureLastChar(':'); + //prefix2.ensureLastChar(':'); + if (prefix2.back() != ':') + { + prefix2.append(1, ':'); + } } //parse arguments - String arg, arg1; + std::string arg, arg1; for (int i = 1; i < argc; ++i) { //load the current and next argument: arg and arg1 ("" at the last argument) @@ -855,7 +865,7 @@ namespace OpenMS //flag (option without text argument) if (arg_is_option && arg1_is_option) { - root_.insert(ParamEntry(arg, String(), ""), prefix2); + root_.insert(ParamEntry(arg, std::string(), ""), prefix2); } //option with argument else if (arg_is_option && !arg1_is_option) @@ -870,14 +880,14 @@ namespace OpenMS ParamEntry* misc_entry = root_.findEntryRecursive(prefix2 + "misc"); if (misc_entry == nullptr) { - StringList sl; + std::vector sl; sl.push_back(arg); // create "misc"-Node: root_.insert(ParamEntry("misc", sl, ""), prefix2); } else { - StringList sl = misc_entry->value; + std::vector sl = misc_entry->value; sl.push_back(arg); misc_entry->value = sl; } @@ -885,16 +895,16 @@ namespace OpenMS } } - void Param::parseCommandLine(const int argc, const char** argv, const Map& options_with_one_argument, const Map& options_without_argument, const Map& options_with_multiple_argument, const String& misc, const String& unknown) + void Param::parseCommandLine(const int argc, const char** argv, const std::map& options_with_one_argument, const std::map& options_without_argument, const std::map& options_with_multiple_argument, const std::string& misc, const std::string& unknown) { //determine misc key - String misc_key = misc; + std::string misc_key = misc; //determine unknown key - String unknown_key = unknown; + std::string unknown_key = unknown; //parse arguments - String arg, arg1; + std::string arg, arg1; for (int i = 1; i < argc; ++i) { //load the current and next argument: arg and arg1 ("" at the last argument) @@ -915,17 +925,17 @@ namespace OpenMS //with multiple argument - if (options_with_multiple_argument.has(arg)) + if (options_with_multiple_argument.find(arg) != options_with_multiple_argument.end()) { //next argument is an option if (arg1_is_option) { - root_.insert(ParamEntry("", StringList(), ""), options_with_multiple_argument.find(arg)->second); + root_.insert(ParamEntry("", std::vector(), ""), options_with_multiple_argument.find(arg)->second); } //next argument is not an option else { - StringList sl; + std::vector sl; int j = (i + 1); while (j < argc && !(arg1.size() >= 2 && arg1[0] == '-' && arg1[1] != '0' && arg1[1] != '1' && arg1[1] != '2' && arg1[1] != '3' && arg1[1] != '4' && arg1[1] != '5' && arg1[1] != '6' && arg1[1] != '7' && arg1[1] != '8' && arg1[1] != '9')) { @@ -940,12 +950,12 @@ namespace OpenMS } } //without argument - else if (options_without_argument.has(arg)) + else if (options_without_argument.find(arg) != options_without_argument.end()) { - root_.insert(ParamEntry("", String("true"), ""), options_without_argument.find(arg)->second); + root_.insert(ParamEntry("", "true", ""), options_without_argument.find(arg)->second); } //with one argument - else if (options_with_one_argument.has(arg)) + else if (options_with_one_argument.find(arg) != options_with_one_argument.end()) { //next argument is not an option if (!arg1_is_option) @@ -957,7 +967,7 @@ namespace OpenMS else { - root_.insert(ParamEntry("", String(), ""), options_with_one_argument.find(arg)->second); + root_.insert(ParamEntry("", std::string(), ""), options_with_one_argument.find(arg)->second); } } //unknown option @@ -966,13 +976,13 @@ namespace OpenMS ParamEntry* unknown_entry = root_.findEntryRecursive(unknown); if (unknown_entry == nullptr) { - StringList sl; + std::vector sl; sl.push_back(arg); root_.insert(ParamEntry("", sl, ""), unknown); } else { - StringList sl = unknown_entry->value; + std::vector sl = unknown_entry->value; sl.push_back(arg); unknown_entry->value = sl; } @@ -983,14 +993,14 @@ namespace OpenMS ParamEntry* misc_entry = root_.findEntryRecursive(misc); if (misc_entry == nullptr) { - StringList sl; + std::vector sl; sl.push_back(arg); // create "misc"-Node: root_.insert(ParamEntry("", sl, ""), misc); } else { - StringList sl = misc_entry->value; + std::vector sl = misc_entry->value; sl.push_back(arg); misc_entry->value = sl; } @@ -1002,12 +1012,12 @@ namespace OpenMS { for (Param::ParamIterator it = param.begin(); it != param.end(); ++it) { - String prefix = it.getName().chop(it->name.size() + 1); - if (prefix != "") + os << '"'; + if (it.getName().length() > it->name.length() + 1) { - prefix += "|"; + os << it.getName().substr(0, it.getName().length() - it->name.length() - 1) << "|"; } - os << '"' << prefix << it->name << "\" -> \"" << it->value << '"'; + os << it->name << "\" -> \"" << it->value << '"'; if (it->description != "") { os << " (" << it->description << ")"; @@ -1017,7 +1027,7 @@ namespace OpenMS return os; } - Size Param::size() const + size_t Param::size() const { return root_.size(); } @@ -1032,13 +1042,15 @@ namespace OpenMS root_ = ParamNode("ROOT", ""); } - void Param::checkDefaults(const String& name, const Param& defaults, const String& prefix) const + void Param::checkDefaults(const std::string& name, const Param& defaults, const std::string& prefix) const { //Extract right parameters - String prefix2 = prefix; + std::string prefix2 = prefix; if (prefix2 != "") { - prefix2.ensureLastChar(':'); + if (prefix2.back() != ':') { + prefix2 += ':'; + } } Param check_values = copy(prefix2, true); @@ -1060,35 +1072,35 @@ namespace OpenMS continue; if (default_value->value.valueType() != it->value.valueType()) { - String d_type; - if (default_value->value.valueType() == DataValue::STRING_VALUE) + std::string d_type; + if (default_value->value.valueType() == ParamValue::STRING_VALUE) d_type = "string"; - if (default_value->value.valueType() == DataValue::STRING_LIST) + if (default_value->value.valueType() == ParamValue::STRING_LIST) d_type = "string list"; - if (default_value->value.valueType() == DataValue::EMPTY_VALUE) + if (default_value->value.valueType() == ParamValue::EMPTY_VALUE) d_type = "empty"; - if (default_value->value.valueType() == DataValue::INT_VALUE) + if (default_value->value.valueType() == ParamValue::INT_VALUE) d_type = "integer"; - if (default_value->value.valueType() == DataValue::INT_LIST) + if (default_value->value.valueType() == ParamValue::INT_LIST) d_type = "integer list"; - if (default_value->value.valueType() == DataValue::DOUBLE_VALUE) + if (default_value->value.valueType() == ParamValue::DOUBLE_VALUE) d_type = "float"; - if (default_value->value.valueType() == DataValue::DOUBLE_LIST) + if (default_value->value.valueType() == ParamValue::DOUBLE_LIST) d_type = "float list"; - String p_type; - if (it->value.valueType() == DataValue::STRING_VALUE) + std::string p_type; + if (it->value.valueType() == ParamValue::STRING_VALUE) p_type = "string"; - if (it->value.valueType() == DataValue::STRING_LIST) + if (it->value.valueType() == ParamValue::STRING_LIST) p_type = "string list"; - if (it->value.valueType() == DataValue::EMPTY_VALUE) + if (it->value.valueType() == ParamValue::EMPTY_VALUE) p_type = "empty"; - if (it->value.valueType() == DataValue::INT_VALUE) + if (it->value.valueType() == ParamValue::INT_VALUE) p_type = "integer"; - if (it->value.valueType() == DataValue::INT_LIST) + if (it->value.valueType() == ParamValue::INT_LIST) p_type = "integer list"; - if (it->value.valueType() == DataValue::DOUBLE_VALUE) + if (it->value.valueType() == ParamValue::DOUBLE_VALUE) p_type = "float"; - if (it->value.valueType() == DataValue::DOUBLE_LIST) + if (it->value.valueType() == ParamValue::DOUBLE_LIST) p_type = "float list"; throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, name + ": Wrong parameter type '" + p_type + "' for " + d_type + " parameter '" + it.getName() + "' given!"); @@ -1096,17 +1108,19 @@ namespace OpenMS //parameter restrictions ParamEntry pe = *default_value; pe.value = it->value; - String s; + std::string s; if (!pe.isValid(s)) throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, name + ": " + s); } } - Param::ParamIterator Param::findFirst(const String& leaf) const + Param::ParamIterator Param::findFirst(const std::string& leaf) const { for (Param::ParamIterator it = this->begin(); it != this->end(); ++it) { - if (it.getName().hasSuffix(String(":") + leaf)) + std::string suffix = ":" + leaf; + if (!(suffix.length() > it.getName().length()) && + it.getName().compare(it.getName().length() - suffix.length(), suffix.length(), suffix) == 0) { return it; } @@ -1114,7 +1128,7 @@ namespace OpenMS return this->end(); } - Param::ParamIterator Param::findNext(const String& leaf, const ParamIterator& start_leaf) const + Param::ParamIterator Param::findNext(const std::string& leaf, const ParamIterator& start_leaf) const { // start at NEXT entry Param::ParamIterator it = start_leaf; @@ -1122,7 +1136,9 @@ namespace OpenMS for (; it != this->end(); ++it) { - if (it.getName().hasSuffix(String(":") + leaf)) + std::string suffix = ":" + leaf; + if (!(suffix.length() > it.getName().length()) && + it.getName().compare(it.getName().length() - suffix.length(), suffix.length(), suffix) == 0) { return it; } @@ -1150,12 +1166,14 @@ namespace OpenMS for (Param::ParamIterator it = p_outdated.begin(); it != p_outdated.end(); ++it) { Param::ParamEntry new_entry; // entry of new location (used to retain new description) - String target_name; // fully qualified name in new param + std::string target_name; // fully qualified name in new param if (this->exists(it.getName())) { // param 'version': do not override! - if (it.getName().hasSuffix(":version")) + std::string suffix = ":version"; + if (!(suffix.length() > it.getName().length()) && + it.getName().compare(it.getName().length() - suffix.length(), suffix.length(), suffix) == 0) { if (this->getValue(it.getName()) != it->value) { @@ -1165,15 +1183,21 @@ OPENMS_THREAD_CRITICAL(oms_log) continue; } // param 'type': do not override! - else if (it.getName().hasSuffix(":type") && - it.getName().toQString().count(':') == 2) // only for TOPP type (e.g. PeakPicker:1:type), any other 'type' param is ok + else if (suffix = ":type", + !(suffix.length() > it.getName().length()) && + it.getName().compare(it.getName().length() - suffix.length(), suffix.length(), suffix) == 0) // only for TOPP type (e.g. PeakPicker:1:type), any other 'type' param is ok { - if (this->getValue(it.getName()) != it->value) + size_t first = it.getName().find(':'); + if (first != std::string::npos && + it.getName().find(':', first+1) != std::string::npos) { -OPENMS_THREAD_CRITICAL(oms_log) - stream << "Warning: for ':type' entry, augmented and Default Ini-File differ in value. Default value will not be altered!\n"; + if (this->getValue(it.getName()) != it->value) + { + OPENMS_THREAD_CRITICAL(oms_log) + stream << "Warning: for ':type' entry, augmented and Default Ini-File differ in value. Default value will not be altered!\n"; + } + continue; } - continue; } // all other parameters: @@ -1215,8 +1239,8 @@ OPENMS_THREAD_CRITICAL(oms_log) OPENMS_THREAD_CRITICAL(oms_log) stream << "Unknown (or deprecated) Parameter '" << it.getName() << "' given in outdated parameter file! Adding to current set." << std::endl; Param::ParamEntry local_entry = p_outdated.getEntry(it.getName()); - String prefix = ""; - if (it.getName().has(':')) + std::string prefix = ""; + if (it.getName().find(':') != std::string::npos) { prefix = it.getName().substr(0, 1 + it.getName().find_last_of(':')); } @@ -1237,9 +1261,9 @@ OPENMS_THREAD_CRITICAL(oms_log) if (new_entry.value != it->value) { // check entry for consistency (in case restrictions have changed) - DataValue default_value = new_entry.value; + ParamValue default_value = new_entry.value; new_entry.value = it->value; - String validation_result; + std::string validation_result; if (new_entry.isValid(validation_result)) { // overwrite default value @@ -1298,13 +1322,13 @@ OPENMS_THREAD_CRITICAL(oms_log) void Param::merge(const OpenMS::Param& toMerge) { // keep track of the path inside the param tree - String pathname; + std::string pathname; // augment for (Param::ParamIterator it = toMerge.begin(); it != toMerge.end(); ++it) { - String prefix = ""; - if (it.getName().has(':')) + std::string prefix = ""; + if (it.getName().find(':') != std::string::npos) prefix = it.getName().substr(0, 1 + it.getName().find_last_of(':')); // we care only about values that do not exist already @@ -1327,14 +1351,15 @@ OPENMS_THREAD_CRITICAL(oms_log) else { OPENMS_LOG_DEBUG << "[Param::merge] reducing param trace " << traceIt->name << " (" << pathname << ")" << std::endl; - if (pathname.hasSuffix(traceIt->name + ":")) + std::string suffix = traceIt->name + ":"; + if (suffix.size() <= pathname.size() && pathname.compare(pathname.size() - suffix.size(), suffix.size(), suffix) == 0) pathname.resize(pathname.size() - traceIt->name.size() - 1); } - String real_pathname = pathname.chop(1); //remove ':' at the end + std::string real_pathname = pathname.substr(0, pathname.size() - 1);//remove ':' at the end if (real_pathname != "") { - String description_old = getSectionDescription(prefix + real_pathname); - String description_new = toMerge.getSectionDescription(real_pathname); + std::string description_old = getSectionDescription(prefix + real_pathname); + std::string description_new = toMerge.getSectionDescription(real_pathname); if (description_old == "") { setSectionDescription(real_pathname, description_new); @@ -1345,7 +1370,7 @@ OPENMS_THREAD_CRITICAL(oms_log) } } - void Param::setSectionDescription(const String& key, const String& description) + void Param::setSectionDescription(const std::string& key, const std::string& description) { ParamNode* node = root_.findParentOf(key); if (node == nullptr) @@ -1361,7 +1386,7 @@ OPENMS_THREAD_CRITICAL(oms_log) it->description = description; } - void Param::addSection(const String& key, const String& description) + void Param::addSection(const std::string& key, const std::string& description) { root_.insert(ParamNode("",description),key); } @@ -1416,7 +1441,7 @@ OPENMS_THREAD_CRITICAL(oms_log) return &(stack_.back()->entries[current_]); } - Param::ParamIterator Param::ParamIterator::operator++(Int) + Param::ParamIterator Param::ParamIterator::operator++(int) { ParamIterator tmp(*this); ++(*this); @@ -1436,7 +1461,7 @@ OPENMS_THREAD_CRITICAL(oms_log) //cout << "############ operator++ #### " << node->name << " ## " << current_ <entries.size()) + if (current_ + 1 < (int)node->entries.size()) { //cout << " - next entry" <name, last->description, false)); //check of new subtree is accessible - UInt next_index = (last - &(node->nodes[0])) + 1; + unsigned int next_index = (last - &(node->nodes[0])) + 1; if (next_index < node->nodes.size()) { current_ = -1; @@ -1503,9 +1528,9 @@ OPENMS_THREAD_CRITICAL(oms_log) return !operator==(rhs); } - String Param::ParamIterator::getName() const + std::string Param::ParamIterator::getName() const { - String tmp; + std::string tmp; for (std::vector::const_iterator it = stack_.begin() + 1; it != stack_.end(); ++it) { tmp += (*it)->name + ':'; @@ -1518,31 +1543,36 @@ OPENMS_THREAD_CRITICAL(oms_log) return trace_; } - const Param::ParamEntry& Param::getEntry(const String& key) const + const Param::ParamEntry& Param::getEntry(const std::string& key) const { return getEntry_(key); } - const String& Param::getDescription(const String& key) const + ParamValue::ValueType Param::getValueType(const std::string& key) const + { + return getEntry_(key).value.valueType(); + } + + const std::string& Param::getDescription(const std::string& key) const { return getEntry_(key).description; } - void Param::addTag(const String& key, const String& tag) + void Param::addTag(const std::string& key, const std::string& tag) { - if (tag.has(',')) + if (tag.find(',') != std::string::npos) { throw Exception::InvalidValue(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Param tags may not contain comma characters", tag); } getEntry_(key).tags.insert(tag); } - void Param::addTags(const String& key, const StringList& tags) + void Param::addTags(const std::string& key, const std::vector& tags) { ParamEntry& entry = getEntry_(key); - for (Size i = 0; i != tags.size(); ++i) + for (size_t i = 0; i != tags.size(); ++i) { - if (tags[i].has(',')) + if (tags[i].find(',') != std::string::npos) { throw Exception::InvalidValue(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Param tags may not contain comma characters", tags[i]); } @@ -1550,33 +1580,46 @@ OPENMS_THREAD_CRITICAL(oms_log) } } - StringList Param::getTags(const String& key) const + std::vector Param::getTags(const std::string& key) const { ParamEntry& entry = getEntry_(key); - StringList list; - for (std::set::const_iterator it = entry.tags.begin(); it != entry.tags.end(); ++it) + std::vector list; + for (std::set::const_iterator it = entry.tags.begin(); it != entry.tags.end(); ++it) { list.push_back(*it); } return list; } - void Param::clearTags(const String& key) + void Param::clearTags(const std::string& key) { getEntry_(key).tags.clear(); } - bool Param::hasTag(const String& key, const String& tag) const + bool Param::hasTag(const std::string& key, const std::string& tag) const { return getEntry_(key).tags.count(tag); } - bool Param::exists(const String& key) const + bool Param::exists(const std::string& key) const { return root_.findEntryRecursive(key); } - Param::ParamEntry& Param::getEntry_(const String& key) const + bool Param::hasSection(const std::string &key) const + { + if (key.back() == ':') + { + // Remove trailing colon from key + return root_.findParentOf(key.substr(0, key.size() - 1)) != nullptr; + } + else + { + return root_.findParentOf(key) != nullptr; + } + } + + Param::ParamEntry& Param::getEntry_(const std::string& key) const { ParamEntry* entry = root_.findEntryRecursive(key); if (entry == nullptr) diff --git a/src/openms/source/DATASTRUCTURES/ParamValue.cpp b/src/openms/source/DATASTRUCTURES/ParamValue.cpp new file mode 100644 index 00000000000..c6819772d05 --- /dev/null +++ b/src/openms/source/DATASTRUCTURES/ParamValue.cpp @@ -0,0 +1,876 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Authors: Ruben Grünberg $ +// -------------------------------------------------------------------------- + +#include + +//#include +#include +#include +#include + +namespace OpenMS +{ + const ParamValue ParamValue::EMPTY; + + // default ctor + ParamValue::ParamValue() : + value_type_(EMPTY_VALUE) + { + } + + // destructor + ParamValue::~ParamValue() + { + clear_(); + } + + //------------------------------------------------------------------- + // ctor for all supported types a ParamValue object can hold + //-------------------------------------------------------------------- + ParamValue::ParamValue(long double p) : + value_type_(DOUBLE_VALUE) + { + data_.dou_ = p; + } + + ParamValue::ParamValue(double p) : + value_type_(DOUBLE_VALUE) + { + data_.dou_ = p; + } + + ParamValue::ParamValue(float p) : + value_type_(DOUBLE_VALUE) + { + data_.dou_ = p; + } + + ParamValue::ParamValue(short int p) : + value_type_(INT_VALUE) + { + data_.ssize_ = p; + } + + ParamValue::ParamValue(unsigned short int p) : + value_type_(INT_VALUE) + { + data_.ssize_ = p; + } + + ParamValue::ParamValue(int p) : + value_type_(INT_VALUE) + { + data_.ssize_ = p; + } + + ParamValue::ParamValue(unsigned int p) : + value_type_(INT_VALUE) + { + data_.ssize_ = p; + } + + ParamValue::ParamValue(long int p) : + value_type_(INT_VALUE) + { + data_.ssize_ = p; + } + + ParamValue::ParamValue(unsigned long int p) : + value_type_(INT_VALUE) + { + data_.ssize_ = p; + } + + ParamValue::ParamValue(long long p) : + value_type_(INT_VALUE) + { + data_.ssize_ = p; + } + + ParamValue::ParamValue(unsigned long long p) : + value_type_(INT_VALUE) + { + data_.ssize_ = p; + } + + ParamValue::ParamValue(const char* p) : + value_type_(STRING_VALUE) + { + data_.str_ = new std::string(p); + } + + ParamValue::ParamValue(const std::string& p) : + value_type_(STRING_VALUE) + { + data_.str_ = new std::string(p); + } + + ParamValue::ParamValue(const std::vector& p) : + value_type_(STRING_LIST) + { + data_.str_list_ = new std::vector(p); + } + + ParamValue::ParamValue(const std::vector& p) : + value_type_(INT_LIST) + { + data_.int_list_ = new std::vector(p); + } + + ParamValue::ParamValue(const std::vector& p) : + value_type_(DOUBLE_LIST) + { + data_.dou_list_ = new std::vector(p); + } + + //-------------------------------------------------------------------- + // copy and move constructors + //-------------------------------------------------------------------- + ParamValue::ParamValue(const ParamValue& p) : + value_type_(p.value_type_) + { + switch (value_type_) + { + case STRING_VALUE: + data_.str_ = new std::string(*p.data_.str_); + break; + case STRING_LIST: + data_.str_list_ = new std::vector(*p.data_.str_list_); + break; + case INT_LIST: + data_.int_list_ = new std::vector(*p.data_.int_list_); + break; + case DOUBLE_LIST: + data_.dou_list_ = new std::vector(*p.data_.dou_list_); + break; + default: + data_ = p.data_; + break; + } + } + + ParamValue::ParamValue(ParamValue&& rhs) noexcept : + value_type_(std::move(rhs.value_type_)), + data_(std::move(rhs.data_)) + { + // clean up rhs, take ownership of data_ + // NOTE: value_type_ == EMPTY_VALUE implies data_ is empty and can be reset + rhs.value_type_ = EMPTY_VALUE; + } + + void ParamValue::clear_() noexcept + { + switch (value_type_) + { + case STRING_VALUE: + delete data_.str_; + break; + case STRING_LIST: + delete data_.str_list_; + break; + case INT_LIST: + delete data_.int_list_; + break; + case DOUBLE_LIST: + delete data_.dou_list_; + break; + default: + break; + } + value_type_ = EMPTY_VALUE; + } + + //-------------------------------------------------------------------- + // copy and move assignment operators + //-------------------------------------------------------------------- + ParamValue& ParamValue::operator=(const ParamValue& p) + { + // Check for self-assignment + if (this == &p) + { + return *this; + } + + // clean up + clear_(); + + // assign + switch (p.value_type_) + { + case STRING_VALUE: + data_.str_ = new std::string(*p.data_.str_); + break; + case STRING_LIST: + data_.str_list_ = new std::vector(*p.data_.str_list_); + break; + case INT_LIST: + data_.int_list_ = new std::vector(*p.data_.int_list_); + break; + case DOUBLE_LIST: + data_.dou_list_ = new std::vector(*p.data_.dou_list_); + break; + default: + data_ = p.data_; + break; + } + + // copy type + value_type_ = p.value_type_; + + return *this; + } + + /// Move assignment operator + ParamValue& ParamValue::operator=(ParamValue&& rhs) noexcept + { + // Check for self-assignment + if (this == &rhs) + { + return *this; + } + + // clean up *this + clear_(); + + // assign values to *this + data_ = rhs.data_; + value_type_ = rhs.value_type_; + // clean up rhs + rhs.value_type_ = EMPTY_VALUE; + + return *this; + } + + //-------------------------------------------------------------------- + // assignment conversion operator + //-------------------------------------------------------------------- + + ParamValue& ParamValue::operator=(const char* arg) + { + clear_(); + data_.str_ = new std::string(arg); + value_type_ = STRING_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const std::string& arg) + { + clear_(); + data_.str_ = new std::string(arg); + value_type_ = STRING_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const std::vector& arg) + { + clear_(); + data_.str_list_ = new std::vector(arg); + value_type_ = STRING_LIST; + return *this; + } + + ParamValue& ParamValue::operator=(const std::vector& arg) + { + clear_(); + data_.int_list_ = new std::vector(arg); + value_type_ = INT_LIST; + return *this; + } + + ParamValue& ParamValue::operator=(const std::vector& arg) + { + clear_(); + data_.dou_list_ = new std::vector(arg); + value_type_ = DOUBLE_LIST; + return *this; + } + + ParamValue& ParamValue::operator=(const long double arg) + { + clear_(); + data_.dou_ = arg; + value_type_ = DOUBLE_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const double arg) + { + clear_(); + data_.dou_ = arg; + value_type_ = DOUBLE_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const float arg) + { + clear_(); + data_.dou_ = arg; + value_type_ = DOUBLE_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const short int arg) + { + clear_(); + data_.ssize_ = arg; + value_type_ = INT_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const unsigned short int arg) + { + clear_(); + data_.ssize_ = arg; + value_type_ = INT_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const int arg) + { + clear_(); + data_.ssize_ = arg; + value_type_ = INT_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const unsigned arg) + { + clear_(); + data_.ssize_ = arg; + value_type_ = INT_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const long int arg) + { + clear_(); + data_.ssize_ = arg; + value_type_ = INT_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const unsigned long arg) + { + clear_(); + data_.ssize_ = arg; + value_type_ = INT_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const long long arg) + { + clear_(); + data_.ssize_ = arg; + value_type_ = INT_VALUE; + return *this; + } + + ParamValue& ParamValue::operator=(const unsigned long long arg) + { + clear_(); + data_.ssize_ = arg; + value_type_ = INT_VALUE; + return *this; + } + + //--------------------------------------------------------------------------- + // Conversion operators + //---------------------------------------------------------------------------- + ParamValue::operator long double() const + { + if (value_type_ == EMPTY_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert ParamValue::EMPTY to long double"); + } + else if (value_type_ == INT_VALUE) + { + return (long double)(data_.ssize_); + } + return data_.dou_; + } + + ParamValue::operator double() const + { + if (value_type_ == EMPTY_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert ParamValue::EMPTY to double"); + } + else if (value_type_ == INT_VALUE) + { + return double(data_.ssize_); + } + return data_.dou_; + } + + ParamValue::operator float() const + { + if (value_type_ == EMPTY_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert ParamValue::EMPTY to float"); + } + else if (value_type_ == INT_VALUE) + { + return float(data_.ssize_); + } + return data_.dou_; + } + + ParamValue::operator short int() const + { + if (value_type_ != INT_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-integer ParamValue to short int"); + } + return data_.ssize_; + } + + ParamValue::operator unsigned short int() const + { + if (value_type_ != INT_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-integer ParamValue to UInt"); + } + if (data_.ssize_ < 0.0) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert negative integer ParamValue to unsigned short int"); + } + return data_.ssize_; + } + + ParamValue::operator int() const + { + if (value_type_ != INT_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-integer ParamValue to int"); + } + return data_.ssize_; + } + + ParamValue::operator unsigned int() const + { + if (value_type_ != INT_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-integer ParamValue to unsigned int"); + } + if (data_.ssize_ < 0.0) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert negative integer ParamValue to unsigned int"); + } + return data_.ssize_; + } + + ParamValue::operator long int() const + { + if (value_type_ != INT_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-integer ParamValue to long int"); + } + return data_.ssize_; + } + + ParamValue::operator unsigned long int() const + { + if (value_type_ != INT_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-integer ParamValue to unsigned long int"); + } + if (data_.ssize_ < 0.0) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert negative integer ParamValue to unsigned long int"); + } + return data_.ssize_; + } + + ParamValue::operator long long() const + { + if (value_type_ != INT_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-integer ParamValue to Int"); + } + return data_.ssize_; + } + + ParamValue::operator unsigned long long() const + { + if (value_type_ != INT_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-integer ParamValue to UInt"); + } + if (data_.ssize_ < 0.0) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert negative integer ParamValue to UInt"); + } + return data_.ssize_; + } + + ParamValue::operator std::string() const + { + if (value_type_ != STRING_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-string ParamValue to string"); + } + return *(data_.str_); + } + + ParamValue::operator std::vector() const + { + return this->toStringVector(); + } + + ParamValue::operator std::vector() const + { + return this->toIntVector(); + } + + ParamValue::operator std::vector() const + { + return this->toDoubleVector(); + } + + // Convert ParamValues to char* + const char* ParamValue::toChar() const + { + switch (value_type_) + { + case STRING_VALUE: + return data_.str_->c_str(); + break; + case EMPTY_VALUE: + return nullptr; + break; + default: + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-string ParamValue to char*"); + break; + } + } + + std::string ParamValue::toString(bool full_precision) const + { + std::string str; + switch (value_type_) + { + case EMPTY_VALUE: + return ""; + break; + case STRING_VALUE: + return *data_.str_; + break; + case INT_VALUE: + return std::to_string(data_.ssize_); + break; + case DOUBLE_VALUE: + { + return doubleToString(data_.dou_, full_precision); + } + break; + case STRING_LIST: + str = "["; + if (!data_.str_list_->empty()) + { + for (std::vector::const_iterator it = data_.str_list_->begin(); + it != data_.str_list_->end() - 1; ++it) + { + str += *it + ", "; + } + str += data_.str_list_->back(); + } + str += "]"; + break; + case INT_LIST: + str = "["; + if (!data_.int_list_->empty()) { + for (std::vector::const_iterator it = data_.int_list_->begin(); + it != data_.int_list_->end() - 1; ++it) + { + str += std::to_string(*it) + ", "; + } + str += std::to_string(data_.int_list_->back()); + } + str += "]"; + break; + case DOUBLE_LIST: + str = "["; + if (!data_.dou_list_->empty()) { + for (std::vector::const_iterator it = data_.dou_list_->begin(); + it != data_.dou_list_->end() - 1; ++it) { + str += doubleToString(*it, full_precision) + ", "; + } + str += doubleToString(data_.dou_list_->back(), full_precision); + } + str += "]"; + break; + default: + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert ParamValue to String"); + break; + } + return str; + } + + std::vector ParamValue::toStringVector() const + { + if (value_type_ != STRING_LIST) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-std::vector ParamValue to std::vector"); + } + return *(data_.str_list_); + } + + std::vector ParamValue::toIntVector() const + { + if (value_type_ != INT_LIST) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-std::vector ParamValue to std::vector"); + } + return *(data_.int_list_); + } + + std::vector ParamValue::toDoubleVector() const { + if (value_type_ != DOUBLE_LIST) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-std::vector ParamValue to std::vector"); + } + return *(data_.dou_list_); + } + + bool ParamValue::toBool() const + { + if (value_type_ != STRING_VALUE) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert non-string ParamValue to bool."); + } + else if (!(*(data_.str_) == "true" || *(data_.str_) == "false")) + { + throw Exception::ConversionError(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Could not convert '" + *(data_.str_) + "' to bool. Valid stings are 'true' and 'false'."); + } + + return *(data_.str_) == "true"; + } + + // ----------------- Comparator ---------------------- + + bool operator==(const ParamValue& a, const ParamValue& b) + { + if (a.value_type_ == b.value_type_) + { + switch (a.value_type_) + { + case ParamValue::EMPTY_VALUE: + return true; + break; + case ParamValue::STRING_VALUE: + return *(a.data_.str_) == *(b.data_.str_); + break; + case ParamValue::STRING_LIST: + return *(a.data_.str_list_) == *(b.data_.str_list_); + break; + case ParamValue::INT_LIST: + return *(a.data_.int_list_) == *(b.data_.int_list_); + break; + case ParamValue::DOUBLE_LIST: + return *(a.data_.dou_list_) == *(b.data_.dou_list_); + break; + case ParamValue::INT_VALUE: + return a.data_.ssize_ == b.data_.ssize_; + break; + case ParamValue::DOUBLE_VALUE: + return a.data_.dou_ == b.data_.dou_; + //return std::fabs(a.data_.dou_ - b.data_.dou_) < 1e-6; This would add an include for + break; + } + } + return false; + } + + bool operator<(const ParamValue& a, const ParamValue& b) + { + if (a.value_type_ == b.value_type_) + { + switch (a.value_type_) + { + case ParamValue::EMPTY_VALUE: + return false; + break; + case ParamValue::STRING_VALUE: + return *(a.data_.str_) < *(b.data_.str_); + break; + case ParamValue::STRING_LIST: + return a.data_.str_list_->size() < b.data_.str_list_->size(); + break; + case ParamValue::INT_LIST: + return a.data_.int_list_->size() < b.data_.int_list_->size(); + break; + case ParamValue::DOUBLE_LIST: + return a.data_.dou_list_->size() < b.data_.dou_list_->size(); + break; + case ParamValue::INT_VALUE: + return a.data_.ssize_ < b.data_.ssize_; + break; + case ParamValue::DOUBLE_VALUE: + return a.data_.dou_ < b.data_.dou_; + break; + } + } + return false; + } + + bool operator>(const ParamValue& a, const ParamValue& b) + { + if (a.value_type_ == b.value_type_) + { + switch (a.value_type_) + { + case ParamValue::EMPTY_VALUE: + return false; + break; + case ParamValue::STRING_VALUE: + return *(a.data_.str_) > *(b.data_.str_); + break; + case ParamValue::STRING_LIST: + return a.data_.str_list_->size() > b.data_.str_list_->size(); + break; + case ParamValue::INT_LIST: + return a.data_.int_list_->size() > b.data_.int_list_->size(); + break; + case ParamValue::DOUBLE_LIST: + return a.data_.dou_list_->size() > b.data_.dou_list_->size(); + break; + case ParamValue::INT_VALUE: + return a.data_.ssize_ > b.data_.ssize_; + break; + case ParamValue::DOUBLE_VALUE: + return a.data_.dou_ > b.data_.dou_; + break; + } + } + return false; + } + + bool operator!=(const ParamValue& a, const ParamValue& b) + { + return !(a == b); + } + + // ----------------- Output operator ---------------------- + + /// for doubles or lists of doubles, you get full precision. Use ParamValue::toString(false) if you only need low precision + std::ostream& operator<<(std::ostream& os, const ParamValue& p) + { + switch (p.value_type_) + { + case ParamValue::STRING_VALUE: + os << *(p.data_.str_); + break; + case ParamValue::STRING_LIST: + os << "["; + if (!p.data_.str_list_->empty()) + { + for (auto it = p.data_.str_list_->begin(), end = p.data_.str_list_->end() - 1; it != end; ++it) + { + os << *it << ", "; + } + os << p.data_.str_list_->back(); + } + os << "]"; + break; + case ParamValue::INT_LIST: + os << "["; + if (!p.data_.int_list_->empty()) + { + for (auto it = p.data_.int_list_->begin(), end = p.data_.int_list_->end() - 1; it != end; ++it) + { + os << *it << ", "; + } + os << p.data_.int_list_->back(); + } + os << "]"; + break; + case ParamValue::DOUBLE_LIST: + os << "["; + if (!p.data_.dou_list_->empty()) + { + for (auto it = p.data_.dou_list_->begin(), end = p.data_.dou_list_->end() - 1; it != end; ++it) + { + os << *it << ", "; + } + os << p.data_.dou_list_->back(); + } + os << "]"; + break; + case ParamValue::INT_VALUE: + os << p.data_.ssize_; + break; + case ParamValue::DOUBLE_VALUE: + os << p.data_.dou_; + break; + case ParamValue::EMPTY_VALUE: + break; + } + return os; + } + + std::string ParamValue::doubleToString(double value, bool full_precision) + { + std::ostringstream os; + std::string s; + if (full_precision) os.precision(15); + else os.precision(3); + if (std::abs(value) >= 10000.0 || + std::abs(value) < 0.001 || + (full_precision && std::abs(value) < 0.01)) + { + os << std::scientific << value; + s = os.str(); + size_t cutoff_end = s.find_last_of('e'); + size_t cutoff_start = s.substr(0, cutoff_end).find_last_not_of('0'); + if (s.at(cutoff_end + 1) == '+') s.erase(cutoff_end + 1, 1); + if (cutoff_start != cutoff_end) + { + if (s.find_first_of('.') == cutoff_start) ++cutoff_start; + s.erase(cutoff_start + 1, cutoff_end - cutoff_start - 1); + } + } + else + { + os << std::fixed << value; + s = os.str(); + size_t cutoff = s.find_last_not_of('0'); + if (cutoff != std::string::npos) + { + if (s.find_first_of('.') == cutoff) ++cutoff; + s.erase(cutoff + 1); + } + } + return s; + } + +} //namespace diff --git a/src/openms/source/DATASTRUCTURES/sources.cmake b/src/openms/source/DATASTRUCTURES/sources.cmake index 96127356c33..40bb4099855 100644 --- a/src/openms/source/DATASTRUCTURES/sources.cmake +++ b/src/openms/source/DATASTRUCTURES/sources.cmake @@ -37,6 +37,7 @@ MatchedIterator.cpp Matrix.cpp OSWData.cpp Param.cpp +ParamValue.cpp QTCluster.cpp String.cpp StringListUtils.cpp diff --git a/src/openms/source/FILTERING/DATAREDUCTION/ElutionPeakDetection.cpp b/src/openms/source/FILTERING/DATAREDUCTION/ElutionPeakDetection.cpp index 376f9a1048c..5bb55ea9c95 100644 --- a/src/openms/source/FILTERING/DATAREDUCTION/ElutionPeakDetection.cpp +++ b/src/openms/source/FILTERING/DATAREDUCTION/ElutionPeakDetection.cpp @@ -58,12 +58,12 @@ namespace OpenMS // like to use the "auto" setting, you will have to call filterByPeakWidth // yourself defaults_.setValue("width_filtering", "fixed", "Enable filtering of unlikely peak widths. The fixed setting filters out mass traces outside the [min_fwhm, max_fwhm] interval (set parameters accordingly!). The auto setting filters with the 5 and 95% quantiles of the peak width distribution."); - defaults_.setValidStrings("width_filtering", ListUtils::create("off,fixed,auto")); - defaults_.setValue("min_fwhm", 1.0, "Minimum full-width-at-half-maximum of chromatographic peaks (in seconds). Ignored if parameter width_filtering is off or auto.", ListUtils::create("advanced")); - defaults_.setValue("max_fwhm", 60.0, "Maximum full-width-at-half-maximum of chromatographic peaks (in seconds). Ignored if parameter width_filtering is off or auto.", ListUtils::create("advanced")); + defaults_.setValidStrings("width_filtering", {"off","fixed","auto"}); + defaults_.setValue("min_fwhm", 1.0, "Minimum full-width-at-half-maximum of chromatographic peaks (in seconds). Ignored if parameter width_filtering is off or auto.", {"advanced"}); + defaults_.setValue("max_fwhm", 60.0, "Maximum full-width-at-half-maximum of chromatographic peaks (in seconds). Ignored if parameter width_filtering is off or auto.", {"advanced"}); - defaults_.setValue("masstrace_snr_filtering", "false", "Apply post-filtering by signal-to-noise ratio after smoothing.", ListUtils::create("advanced")); - defaults_.setValidStrings("masstrace_snr_filtering", ListUtils::create("true,false")); + defaults_.setValue("masstrace_snr_filtering", "false", "Apply post-filtering by signal-to-noise ratio after smoothing.", {"advanced"}); + defaults_.setValidStrings("masstrace_snr_filtering", {"true","false"}); defaultsToParam_(); this->setLogType(CMD); @@ -617,7 +617,7 @@ namespace OpenMS min_fwhm_ = (double)param_.getValue("min_fwhm"); max_fwhm_ = (double)param_.getValue("max_fwhm"); - pw_filtering_ = param_.getValue("width_filtering"); + pw_filtering_ = param_.getValue("width_filtering").toString(); mt_snr_filtering_ = param_.getValue("masstrace_snr_filtering").toBool(); } diff --git a/src/openms/source/FILTERING/DATAREDUCTION/FeatureFindingMetabo.cpp b/src/openms/source/FILTERING/DATAREDUCTION/FeatureFindingMetabo.cpp index 6f663236e9d..5861a434746 100644 --- a/src/openms/source/FILTERING/DATAREDUCTION/FeatureFindingMetabo.cpp +++ b/src/openms/source/FILTERING/DATAREDUCTION/FeatureFindingMetabo.cpp @@ -264,36 +264,36 @@ namespace OpenMS FeatureFindingMetabo::FeatureFindingMetabo() : DefaultParamHandler("FeatureFindingMetabo"), ProgressLogger() { - defaults_.setValue("local_rt_range", 10.0, "RT range where to look for coeluting mass traces", ListUtils::create("advanced")); // 5.0 - defaults_.setValue("local_mz_range", 6.5, "MZ range where to look for isotopic mass traces", ListUtils::create("advanced")); // 6.5 + defaults_.setValue("local_rt_range", 10.0, "RT range where to look for coeluting mass traces", {"advanced"}); // 5.0 + defaults_.setValue("local_mz_range", 6.5, "MZ range where to look for isotopic mass traces", {"advanced"}); // 6.5 defaults_.setValue("charge_lower_bound", 1, "Lowest charge state to consider"); // 1 defaults_.setValue("charge_upper_bound", 3, "Highest charge state to consider"); // 3 defaults_.setValue("chrom_fwhm", 5.0, "Expected chromatographic peak width (in seconds)."); // 5.0 - defaults_.setValue("report_summed_ints", "false", "Set to true for a feature intensity summed up over all traces rather than using monoisotopic trace intensity alone.", ListUtils::create("advanced")); - defaults_.setValidStrings("report_summed_ints", ListUtils::create("false,true")); + defaults_.setValue("report_summed_ints", "false", "Set to true for a feature intensity summed up over all traces rather than using monoisotopic trace intensity alone.", {"advanced"}); + defaults_.setValidStrings("report_summed_ints", {"false","true"}); defaults_.setValue("enable_RT_filtering", "true", "Require sufficient overlap in RT while assembling mass traces. Disable for direct injection data.."); - defaults_.setValidStrings("enable_RT_filtering", ListUtils::create("false,true")); + defaults_.setValidStrings("enable_RT_filtering", {"false","true"}); defaults_.setValue("isotope_filtering_model", "metabolites (5% RMS)", "Remove/score candidate assemblies based on isotope intensities. SVM isotope models for metabolites were trained with either 2% or 5% RMS error. For peptides, an averagine cosine scoring is used. Select the appropriate noise model according to the quality of measurement or MS device."); - defaults_.setValidStrings("isotope_filtering_model", ListUtils::create("metabolites (2% RMS),metabolites (5% RMS),peptides,none")); + defaults_.setValidStrings("isotope_filtering_model", {"metabolites (2% RMS)","metabolites (5% RMS)","peptides","none"}); defaults_.setValue("mz_scoring_13C", "false", "Use the 13C isotope peak position (~1.003355 Da) as the expected shift in m/z for isotope mass traces (highly recommended for lipidomics!). Disable for general metabolites (as described in Kenar et al. 2014, MCP.)."); - defaults_.setValidStrings("mz_scoring_13C", ListUtils::create("false,true")); + defaults_.setValidStrings("mz_scoring_13C", {"false","true"}); - defaults_.setValue("use_smoothed_intensities", "true", "Use LOWESS intensities instead of raw intensities.", ListUtils::create("advanced")); - defaults_.setValidStrings("use_smoothed_intensities", ListUtils::create("false,true")); + defaults_.setValue("use_smoothed_intensities", "true", "Use LOWESS intensities instead of raw intensities.", {"advanced"}); + defaults_.setValidStrings("use_smoothed_intensities", {"false","true"}); defaults_.setValue("report_convex_hulls", "false", "Augment each reported feature with the convex hull of the underlying mass traces (increases featureXML file size considerably)."); - defaults_.setValidStrings("report_convex_hulls", ListUtils::create("false,true")); + defaults_.setValidStrings("report_convex_hulls", {"false","true"}); defaults_.setValue("report_chromatograms", "false", "Adds Chromatogram for each reported feature (Output in mzml)."); - defaults_.setValidStrings("report_chromatograms", ListUtils::create("false,true")); + defaults_.setValidStrings("report_chromatograms", {"false","true"}); defaults_.setValue("remove_single_traces", "false", "Remove unassembled traces (single traces)."); - defaults_.setValidStrings("remove_single_traces", ListUtils::create("false,true")); + defaults_.setValidStrings("remove_single_traces", {"false","true"}); defaults_.setValue("mz_scoring_by_elements", "false", "Use the m/z range of the assumed elements to detect isotope peaks. A expected m/z range is computed from the isotopes of the assumed elements. If enabled, this ignores 'mz_scoring_13C'"); - defaults_.setValidStrings("mz_scoring_by_elements", ListUtils::create("false,true")); + defaults_.setValidStrings("mz_scoring_by_elements", {"false","true"}); defaults_.setValue("elements", "CHNOPS", "Elements assumes to be present in the sample (this influences isotope detection)."); @@ -322,7 +322,7 @@ namespace OpenMS report_summed_ints_ = param_.getValue("report_summed_ints").toBool(); enable_RT_filtering_ = param_.getValue("enable_RT_filtering").toBool(); - isotope_filtering_model_ = param_.getValue("isotope_filtering_model"); + isotope_filtering_model_ = param_.getValue("isotope_filtering_model").toString(); use_smoothed_intensities_ = param_.getValue("use_smoothed_intensities").toBool(); use_mz_scoring_C13_ = param_.getValue("mz_scoring_13C").toBool(); diff --git a/src/openms/source/FILTERING/DATAREDUCTION/MassTraceDetection.cpp b/src/openms/source/FILTERING/DATAREDUCTION/MassTraceDetection.cpp index 8f0ecc32d6f..6b9d0e27cb8 100644 --- a/src/openms/source/FILTERING/DATAREDUCTION/MassTraceDetection.cpp +++ b/src/openms/source/FILTERING/DATAREDUCTION/MassTraceDetection.cpp @@ -48,19 +48,19 @@ namespace OpenMS defaults_.setValue("chrom_peak_snr", 3.0, "Minimum intensity above noise_threshold_int (signal-to-noise) a peak should have to be considered an apex."); defaults_.setValue("reestimate_mt_sd", "true", "Enables dynamic re-estimation of m/z variance during mass trace collection stage."); - defaults_.setValidStrings("reestimate_mt_sd", ListUtils::create("true,false")); + defaults_.setValidStrings("reestimate_mt_sd", {"true","false"}); defaults_.setValue("quant_method", String(MassTrace::names_of_quantmethod[0]), "Method of quantification for mass traces. For LC data 'area' is recommended, 'median' for direct injection data. 'max_height' simply uses the most intense peak in the trace."); - defaults_.setValidStrings("quant_method", std::vector(MassTrace::names_of_quantmethod, MassTrace::names_of_quantmethod +(int)MassTrace::SIZE_OF_MT_QUANTMETHOD)); + defaults_.setValidStrings("quant_method", std::vector(MassTrace::names_of_quantmethod, MassTrace::names_of_quantmethod +(int)MassTrace::SIZE_OF_MT_QUANTMETHOD)); // advanced parameters - defaults_.setValue("trace_termination_criterion", "outlier", "Termination criterion for the extension of mass traces. In 'outlier' mode, trace extension cancels if a predefined number of consecutive outliers are found (see trace_termination_outliers parameter). In 'sample_rate' mode, trace extension in both directions stops if ratio of found peaks versus visited spectra falls below the 'min_sample_rate' threshold.", ListUtils::create("advanced")); - defaults_.setValidStrings("trace_termination_criterion", ListUtils::create("outlier,sample_rate")); - defaults_.setValue("trace_termination_outliers", 5, "Mass trace extension in one direction cancels if this number of consecutive spectra with no detectable peaks is reached.", ListUtils::create("advanced")); + defaults_.setValue("trace_termination_criterion", "outlier", "Termination criterion for the extension of mass traces. In 'outlier' mode, trace extension cancels if a predefined number of consecutive outliers are found (see trace_termination_outliers parameter). In 'sample_rate' mode, trace extension in both directions stops if ratio of found peaks versus visited spectra falls below the 'min_sample_rate' threshold.", {"advanced"}); + defaults_.setValidStrings("trace_termination_criterion", {"outlier","sample_rate"}); + defaults_.setValue("trace_termination_outliers", 5, "Mass trace extension in one direction cancels if this number of consecutive spectra with no detectable peaks is reached.", {"advanced"}); - defaults_.setValue("min_sample_rate", 0.5, "Minimum fraction of scans along the mass trace that must contain a peak.", ListUtils::create("advanced")); - defaults_.setValue("min_trace_length", 5.0, "Minimum expected length of a mass trace (in seconds).", ListUtils::create("advanced")); - defaults_.setValue("max_trace_length", -1.0, "Maximum expected length of a mass trace (in seconds). Set to a negative value to disable maximal length check during mass trace detection.", ListUtils::create("advanced")); + defaults_.setValue("min_sample_rate", 0.5, "Minimum fraction of scans along the mass trace that must contain a peak.", {"advanced"}); + defaults_.setValue("min_trace_length", 5.0, "Minimum expected length of a mass trace (in seconds).", {"advanced"}); + defaults_.setValue("max_trace_length", -1.0, "Maximum expected length of a mass trace (in seconds). Set to a negative value to disable maximal length check during mass trace detection.", {"advanced"}); defaultsToParam_(); @@ -567,9 +567,9 @@ namespace OpenMS mass_error_ppm_ = (double)param_.getValue("mass_error_ppm"); noise_threshold_int_ = (double)param_.getValue("noise_threshold_int"); chrom_peak_snr_ = (double)param_.getValue("chrom_peak_snr"); - quant_method_ = MassTrace::getQuantMethod((String)param_.getValue("quant_method")); + quant_method_ = MassTrace::getQuantMethod((String)param_.getValue("quant_method").toString()); - trace_termination_criterion_ = (String)param_.getValue("trace_termination_criterion"); + trace_termination_criterion_ = (String)param_.getValue("trace_termination_criterion").toString(); trace_termination_outliers_ = (Size)param_.getValue("trace_termination_outliers"); min_sample_rate_ = (double)param_.getValue("min_sample_rate"); min_trace_length_ = (double)param_.getValue("min_trace_length"); diff --git a/src/openms/source/FILTERING/ID/IDFilter.cpp b/src/openms/source/FILTERING/ID/IDFilter.cpp index 3f3c92f8ba2..dfc14c40213 100644 --- a/src/openms/source/FILTERING/ID/IDFilter.cpp +++ b/src/openms/source/FILTERING/ID/IDFilter.cpp @@ -35,18 +35,12 @@ #include #include +#include + using namespace std; namespace OpenMS { - IDFilter::IDFilter() - { - } - - IDFilter::~IDFilter() - { - } - struct IDFilter::HasMinPeptideLength { @@ -671,6 +665,23 @@ namespace OpenMS } } + void IDFilter::removePeptidesWithMatchingRegEx( + vector& peptides, + const String& regex) + { + const std::regex re(regex); + + // true if regex matches to parts or entire unmodified sequence + auto regex_matches = [&re](const PeptideHit& ph) -> bool + { + return std::regex_search(ph.getSequence().toUnmodifiedString(), re); + }; + + for (auto& pep : peptides) + { + removeMatchingItems(pep.getHits(), regex_matches); + } + } void IDFilter::keepPeptidesWithMatchingModifications( vector& peptides, diff --git a/src/openms/source/FILTERING/SMOOTHING/GaussFilter.cpp b/src/openms/source/FILTERING/SMOOTHING/GaussFilter.cpp index 766ea9904c3..34e83597613 100644 --- a/src/openms/source/FILTERING/SMOOTHING/GaussFilter.cpp +++ b/src/openms/source/FILTERING/SMOOTHING/GaussFilter.cpp @@ -46,7 +46,7 @@ namespace OpenMS defaults_.setValue("gaussian_width", 0.2, "Use a gaussian filter width which has approximately the same width as your mass peaks (FWHM in m/z)."); defaults_.setValue("ppm_tolerance", 10.0, "Gaussian width, depending on the m/z position.\nThe higher the value, the wider the peak and therefore the wider the gaussian."); defaults_.setValue("use_ppm_tolerance", "false", "If true, instead of the gaussian_width value, the ppm_tolerance is used. The gaussian is calculated in each step anew, so this is much slower."); - defaults_.setValidStrings("use_ppm_tolerance", ListUtils::create("true,false")); + defaults_.setValidStrings("use_ppm_tolerance", {"true","false"}); defaultsToParam_(); } diff --git a/src/openms/source/FILTERING/TRANSFORMERS/BernNorm.cpp b/src/openms/source/FILTERING/TRANSFORMERS/BernNorm.cpp index 20949e82462..785848fc734 100644 --- a/src/openms/source/FILTERING/TRANSFORMERS/BernNorm.cpp +++ b/src/openms/source/FILTERING/TRANSFORMERS/BernNorm.cpp @@ -48,8 +48,8 @@ namespace OpenMS // values from the paper // they should be good for GoodDiff and Complements // IsotopeDiffs needs lower peaks - defaults_.setValue("C1", 28.0, "C1 value of the normalization.", ListUtils::create("advanced")); - defaults_.setValue("C2", 400.0, "C2 value of the normalization.", ListUtils::create("advanced")); + defaults_.setValue("C1", 28.0, "C1 value of the normalization.", {"advanced"}); + defaults_.setValue("C2", 400.0, "C2 value of the normalization.", {"advanced"}); defaults_.setValue("threshold", 0.1, "Threshold of the Bern et al. normalization."); // i.e. what is a significant peak defaultsToParam_(); c1_ = 28.0; diff --git a/src/openms/source/FILTERING/TRANSFORMERS/Normalizer.cpp b/src/openms/source/FILTERING/TRANSFORMERS/Normalizer.cpp index 608d9477246..a3c554dc37f 100644 --- a/src/openms/source/FILTERING/TRANSFORMERS/Normalizer.cpp +++ b/src/openms/source/FILTERING/TRANSFORMERS/Normalizer.cpp @@ -42,7 +42,7 @@ namespace OpenMS DefaultParamHandler("Normalizer") { defaults_.setValue("method", "to_one", "Normalize via dividing by TIC ('to_TIC') per spectrum or normalize to max. intensity of one ('to_one') per spectrum."); - defaults_.setValidStrings("method", ListUtils::create("to_one,to_TIC")); + defaults_.setValidStrings("method", {"to_one","to_TIC"}); defaultsToParam_(); } @@ -79,7 +79,7 @@ namespace OpenMS void Normalizer::updateMembers_() { - method_ = param_.getValue("method"); + method_ = param_.getValue("method").toString(); } } diff --git a/src/openms/source/FILTERING/TRANSFORMERS/ParentPeakMower.cpp b/src/openms/source/FILTERING/TRANSFORMERS/ParentPeakMower.cpp index bea532ce54c..4801ecd1b1a 100644 --- a/src/openms/source/FILTERING/TRANSFORMERS/ParentPeakMower.cpp +++ b/src/openms/source/FILTERING/TRANSFORMERS/ParentPeakMower.cpp @@ -44,12 +44,12 @@ namespace OpenMS { defaults_.setValue("window_size", 2.0, "The size of the m/z window where the peaks are removed, +/- window_size."); defaults_.setValue("default_charge", 2, "If the precursor has no charge set, the default charge is assumed."); - defaults_.setValue("clean_all_charge_states", 1, "Set to 1 if precursor ions of all possible charge states should be removed.", ListUtils::create("advanced")); + defaults_.setValue("clean_all_charge_states", 1, "Set to 1 if precursor ions of all possible charge states should be removed.", {"advanced"}); defaults_.setValue("consider_NH3_loss", 1, "Whether NH3 loss peaks from the precursor should be removed."); defaults_.setValue("consider_H2O_loss", 1, "Whether H2O loss peaks from the precursor should be removed."); - defaults_.setValue("reduce_by_factor", 0, "Reduce the intensities of the precursor and related ions by a given factor (set 'set_to_zero' to 0).", ListUtils::create("advanced")); - defaults_.setValue("factor", 1000.0, "Factor which is used to reduce the intensities if 'reduce_by_factor' is selected.", ListUtils::create("advanced")); - defaults_.setValue("set_to_zero", 1, "Reduce the intensities of the precursor and related ions to zero.", ListUtils::create("advanced")); + defaults_.setValue("reduce_by_factor", 0, "Reduce the intensities of the precursor and related ions by a given factor (set 'set_to_zero' to 0).", {"advanced"}); + defaults_.setValue("factor", 1000.0, "Factor which is used to reduce the intensities if 'reduce_by_factor' is selected.", {"advanced"}); + defaults_.setValue("set_to_zero", 1, "Reduce the intensities of the precursor and related ions to zero.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/FILTERING/TRANSFORMERS/SpectraMerger.cpp b/src/openms/source/FILTERING/TRANSFORMERS/SpectraMerger.cpp index 1a9f13c4636..4870fa2147a 100644 --- a/src/openms/source/FILTERING/TRANSFORMERS/SpectraMerger.cpp +++ b/src/openms/source/FILTERING/TRANSFORMERS/SpectraMerger.cpp @@ -43,37 +43,37 @@ namespace OpenMS DefaultParamHandler("SpectraMerger") { // common - defaults_.setValue("mz_binning_width", 5.0, "minimum m/z distance for two data points (profile data) or peaks (centroided data) to be considered distinct. Closer data points or peaks will be merged.", ListUtils::create("advanced")); + defaults_.setValue("mz_binning_width", 5.0, "minimum m/z distance for two data points (profile data) or peaks (centroided data) to be considered distinct. Closer data points or peaks will be merged.", {"advanced"}); defaults_.setMinFloat("mz_binning_width", 0.0); - defaults_.setValue("mz_binning_width_unit", "ppm", "Unit in which the distance between two data points or peaks is given.", ListUtils::create("advanced")); - defaults_.setValidStrings("mz_binning_width_unit", ListUtils::create("Da,ppm")); + defaults_.setValue("mz_binning_width_unit", "ppm", "Unit in which the distance between two data points or peaks is given.", {"advanced"}); + defaults_.setValidStrings("mz_binning_width_unit", {"Da","ppm"}); - defaults_.setValue("sort_blocks", "RT_ascending", "Sort blocks by before merging them (useful for precursor order)", ListUtils::create("advanced")); - defaults_.setValidStrings("sort_blocks", ListUtils::create("RT_ascending, RT_descending")); + defaults_.setValue("sort_blocks", "RT_ascending", "Sort blocks by before merging them (useful for precursor order)", {"advanced"}); + defaults_.setValidStrings("sort_blocks", {"RT_ascending","RT_descending"}); // Gaussian average defaults_.setValue("average_gaussian:spectrum_type", "automatic", "Spectrum type of the MS level to be averaged"); - defaults_.setValidStrings("average_gaussian:spectrum_type", ListUtils::create("profile,centroid,automatic")); + defaults_.setValidStrings("average_gaussian:spectrum_type", {"profile","centroid","automatic"}); defaults_.setValue("average_gaussian:ms_level", 1, "Average spectra of this level. All other spectra remain unchanged."); defaults_.setMinInt("average_gaussian:ms_level", 1); defaults_.setValue("average_gaussian:rt_FWHM", 5.0, "FWHM of Gauss curve in seconds to be averaged over."); defaults_.setMinFloat("average_gaussian:rt_FWHM", 0.0); defaults_.setMaxFloat("average_gaussian:rt_FWHM", 10e10); - defaults_.setValue("average_gaussian:cutoff", 0.01, "Intensity cutoff for Gaussian. The Gaussian RT profile decreases from 1 at its apex to 0 at infinity. Spectra for which the intensity of the Gaussian drops below the cutoff do not contribute to the average.", ListUtils::create("advanced")); + defaults_.setValue("average_gaussian:cutoff", 0.01, "Intensity cutoff for Gaussian. The Gaussian RT profile decreases from 1 at its apex to 0 at infinity. Spectra for which the intensity of the Gaussian drops below the cutoff do not contribute to the average.", {"advanced"}); defaults_.setMinFloat("average_gaussian:cutoff", 0.0); defaults_.setMaxFloat("average_gaussian:cutoff", 1.0); // top-hat average defaults_.setValue("average_tophat:spectrum_type", "automatic", "Spectrum type of the MS level to be averaged"); - defaults_.setValidStrings("average_tophat:spectrum_type", ListUtils::create("profile,centroid,automatic")); + defaults_.setValidStrings("average_tophat:spectrum_type", {"profile","centroid","automatic"}); defaults_.setValue("average_tophat:ms_level", 1, "Average spectra of this level. All other spectra remain unchanged."); defaults_.setMinInt("average_tophat:ms_level", 1); defaults_.setValue("average_tophat:rt_range", 5.0, "RT range to be averaged over, i.e. +/-(RT range)/2 from each spectrum."); defaults_.setMinFloat("average_tophat:rt_range", 0.0); defaults_.setMaxFloat("average_tophat:rt_range", 10e10); defaults_.setValue("average_tophat:rt_unit", "scans", "Unit for RT range."); - defaults_.setValidStrings("average_tophat:rt_unit", ListUtils::create("scans,seconds")); + defaults_.setValidStrings("average_tophat:rt_unit", {"scans","seconds"}); // block merging defaults_.setValue("block_method:ms_levels", ListUtils::create("1"), "Merge spectra of this level. All spectra with other MS levels remain untouched."); diff --git a/src/openms/source/FILTERING/TRANSFORMERS/WindowMower.cpp b/src/openms/source/FILTERING/TRANSFORMERS/WindowMower.cpp index 0ad9391dca8..315ce41aa95 100644 --- a/src/openms/source/FILTERING/TRANSFORMERS/WindowMower.cpp +++ b/src/openms/source/FILTERING/TRANSFORMERS/WindowMower.cpp @@ -45,7 +45,7 @@ namespace OpenMS defaults_.setValue("windowsize", 50.0, "The size of the sliding window along the m/z axis."); defaults_.setValue("peakcount", 2, "The number of peaks that should be kept."); defaults_.setValue("movetype", "slide", "Whether sliding window (one peak steps) or jumping window (window size steps) should be used."); - defaults_.setValidStrings("movetype", ListUtils::create("slide,jump")); + defaults_.setValidStrings("movetype", {"slide","jump"}); defaultsToParam_(); } @@ -69,7 +69,7 @@ namespace OpenMS void WindowMower::filterPeakSpectrum(PeakSpectrum & spectrum) { - bool sliding = (String)param_.getValue("movetype") == "slide" ? true : false; + bool sliding = param_.getValue("movetype").toString() == "slide" ? true : false; if (sliding) { @@ -83,7 +83,7 @@ namespace OpenMS void WindowMower::filterPeakMap(PeakMap & exp) { - bool sliding = (String)param_.getValue("movetype") == "slide" ? true : false; + bool sliding = param_.getValue("movetype").toString() == "slide" ? true : false; for (PeakMap::Iterator it = exp.begin(); it != exp.end(); ++it) { if (sliding) diff --git a/src/openms/source/FORMAT/AbsoluteQuantitationMethodFile.cpp b/src/openms/source/FORMAT/AbsoluteQuantitationMethodFile.cpp index a7ce0cd7d75..7542a9d8296 100644 --- a/src/openms/source/FORMAT/AbsoluteQuantitationMethodFile.cpp +++ b/src/openms/source/FORMAT/AbsoluteQuantitationMethodFile.cpp @@ -165,7 +165,7 @@ namespace OpenMS const Param tm_params = aqm.getTransformationModelParams(); for (Size i = 0, j = 11; i < tm_params_names.size(); ++i, ++j) { - row[j] = tm_params.exists(tm_params_names[i]) ? tm_params.getValue(tm_params_names[i]) : ""; + row[j] = tm_params.exists(tm_params_names[i]) ? tm_params.getValue(tm_params_names[i]).toString() : ""; } addRow(row); } diff --git a/src/openms/source/FORMAT/DATAACCESS/SiriusMzTabWriter.cpp b/src/openms/source/FORMAT/DATAACCESS/SiriusMzTabWriter.cpp index f69ec0aa641..731a6324307 100644 --- a/src/openms/source/FORMAT/DATAACCESS/SiriusMzTabWriter.cpp +++ b/src/openms/source/FORMAT/DATAACCESS/SiriusMzTabWriter.cpp @@ -45,13 +45,13 @@ using namespace std; int SiriusMzTabWriter::extractScanIndex(const String& path) { - boost::regex regexp_ind("--(?\\d+)--"); + boost::regex regexp_ind(R"(--(?\d+)--)"); return SpectrumLookup::extractScanNumber(path, regexp_ind, false); } int SiriusMzTabWriter::extractScanNumber(const String& path) { - boost::regex regexp("-(?\\d+)--"); + boost::regex regexp(R"(-(?\d+)--)"); return SpectrumLookup::extractScanNumber(path, regexp, false); } @@ -59,7 +59,7 @@ String SiriusMzTabWriter::extractFeatureId(const String& path) { boost::smatch match; String feature_id; - boost::regex regexp_feature("_(?\\d+)-"); + boost::regex regexp_feature(R"(_(?\d+)-)"); bool found = boost::regex_search(path, match, regexp_feature); if (found && match["SCAN"].matched) { diff --git a/src/openms/source/FORMAT/FASTAFile.cpp b/src/openms/source/FORMAT/FASTAFile.cpp index 3d0fe861014..bd9ecafb240 100644 --- a/src/openms/source/FORMAT/FASTAFile.cpp +++ b/src/openms/source/FORMAT/FASTAFile.cpp @@ -149,8 +149,9 @@ namespace OpenMS return seqan::atEnd(*static_cast(reader_.get())); } - void FASTAFile::load(const String& filename, vector& data) + void FASTAFile::load(const String& filename, vector& data) const { + startProgress(0, 1, "Loading FASTA file"); data.clear(); FASTAEntry p; FASTAFile f; @@ -159,6 +160,7 @@ namespace OpenMS { data.push_back(std::move(p)); } + endProgress(); return; } @@ -203,15 +205,18 @@ namespace OpenMS outfile_.close(); } - void FASTAFile::store(const String& filename, const vector& data) + void FASTAFile::store(const String& filename, const vector& data) const { + startProgress(0, data.size(), "Writing FASTA file"); FASTAFile f; f.writeStart(filename); for (vector::const_iterator it = data.begin(); it != data.end(); ++it) { f.writeNext(*it); + nextProgress(); } f.writeEnd(); // close file + endProgress(); } } // namespace OpenMS diff --git a/src/openms/source/FORMAT/FileHandler.cpp b/src/openms/source/FORMAT/FileHandler.cpp index c04ee4943ac..4dd00060222 100644 --- a/src/openms/source/FORMAT/FileHandler.cpp +++ b/src/openms/source/FORMAT/FileHandler.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -155,6 +156,27 @@ namespace OpenMS } } + FileTypes::Type FileHandler::getConsistentOutputfileType(const String& output_filename, const String& requested_type) + { + FileTypes::Type t_file = getTypeByFileName(output_filename); + FileTypes::Type t_req = FileTypes::nameToType(requested_type); + // both UNKNOWN + if (t_file == FileTypes::Type::UNKNOWN && t_req == FileTypes::Type::UNKNOWN) + { + OPENMS_LOG_ERROR << "Type of '" << output_filename << "' and requested output type '" << requested_type << "' are both unknown." << std::endl; + return FileTypes::Type::UNKNOWN; + } + // or inconsistent (while both are known) + if ((t_file != t_req) && (t_file != FileTypes::Type::UNKNOWN) + (t_req != FileTypes::Type::UNKNOWN) == 2) + { + OPENMS_LOG_ERROR << "Type of '" << output_filename << "' and requested output type '" << requested_type << "' are inconsistent." << std::endl; + return FileTypes::Type::UNKNOWN; + } + + if (t_file != FileTypes::Type::UNKNOWN) return t_file; + else return t_req; + } + FileTypes::Type FileHandler::getTypeByContent(const String& filename) { String first_line; @@ -586,7 +608,7 @@ if (first_line.hasSubstring("File First Scan Last Scan Num of Scans Charge Monoi } } - //load right file + // load right file switch (type) { case FileTypes::DTA: @@ -596,65 +618,60 @@ if (first_line.hasSubstring("File First Scan Last Scan Num of Scans Charge Monoi break; case FileTypes::DTA2D: - { - DTA2DFile f; - f.getOptions() = options_; - f.setLogType(log); - f.load(filename, exp); - } - - break; + { + DTA2DFile f; + f.getOptions() = options_; + f.setLogType(log); + f.load(filename, exp); + } + break; case FileTypes::MZXML: - { - MzXMLFile f; - f.getOptions() = options_; - f.setLogType(log); - f.load(filename, exp); - } - - break; + { + MzXMLFile f; + f.getOptions() = options_; + f.setLogType(log); + f.load(filename, exp); + } + break; case FileTypes::MZDATA: - { - MzDataFile f; - f.getOptions() = options_; - f.setLogType(log); - f.load(filename, exp); - } - break; + { + MzDataFile f; + f.getOptions() = options_; + f.setLogType(log); + f.load(filename, exp); + } + break; case FileTypes::MZML: - { - MzMLFile f; - f.getOptions() = options_; - f.setLogType(log); - f.load(filename, exp); - ChromatogramTools().convertSpectraToChromatograms(exp, true); - } - break; + { + MzMLFile f; + f.getOptions() = options_; + f.setLogType(log); + f.load(filename, exp); + ChromatogramTools().convertSpectraToChromatograms(exp, true); + } + break; case FileTypes::MGF: - { - MascotGenericFile f; - f.setLogType(log); - f.load(filename, exp); - } - - break; + { + MascotGenericFile f; + f.setLogType(log); + f.load(filename, exp); + } + break; case FileTypes::MS2: - { - MS2File f; - f.setLogType(log); - f.load(filename, exp); - } - - break; + { + MS2File f; + f.setLogType(log); + f.load(filename, exp); + } + break; case FileTypes::SQMASS: SqMassFile().load(filename, exp); - break; case FileTypes::XMASS: @@ -662,7 +679,10 @@ if (first_line.hasSubstring("File First Scan Last Scan Num of Scans Charge Monoi exp.resize(1); XMassFile().load(filename, exp[0]); XMassFile().importExperimentalSettings(filename, exp); - + break; + + case FileTypes::MSP: + MSPGenericFile().load(filename, exp); break; default: diff --git a/src/openms/source/FORMAT/HANDLERS/IndexedMzMLDecoder.cpp b/src/openms/source/FORMAT/HANDLERS/IndexedMzMLDecoder.cpp index efb3b6e98f3..e733aedb91c 100644 --- a/src/openms/source/FORMAT/HANDLERS/IndexedMzMLDecoder.cpp +++ b/src/openms/source/FORMAT/HANDLERS/IndexedMzMLDecoder.cpp @@ -177,7 +177,7 @@ namespace OpenMS // Since we could be anywhere in the XML structure, use regex to find // indexListOffset and read its content. //------------------------------------------------------------- - boost::regex listoffset_rx("<[^>/]*indexListOffset\\s*>\\s*(\\d*)"); + boost::regex listoffset_rx(R"(<[^>/]*indexListOffset\s*>\s*(\d*))"); boost::cmatch matches; boost::regex_search(buffer.get(), matches, listoffset_rx); String thismatch(matches[1].first, matches[1].second); diff --git a/src/openms/source/FORMAT/HANDLERS/IndexedMzMLHandler.cpp b/src/openms/source/FORMAT/HANDLERS/IndexedMzMLHandler.cpp index e216582c4ae..17ad140a7e6 100644 --- a/src/openms/source/FORMAT/HANDLERS/IndexedMzMLHandler.cpp +++ b/src/openms/source/FORMAT/HANDLERS/IndexedMzMLHandler.cpp @@ -45,13 +45,13 @@ namespace OpenMS namespace Internal { - void IndexedMzMLHandler::parseFooter_(String filename) + void IndexedMzMLHandler::parseFooter_() { //------------------------------------------------------------- // Find offset //------------------------------------------------------------- - index_offset_ = IndexedMzMLDecoder().findIndexListOffset(filename); + index_offset_ = IndexedMzMLDecoder().findIndexListOffset(filename_); if (index_offset_ == (std::streampos)-1) { parsing_success_ = false; @@ -61,7 +61,7 @@ namespace Internal // typedef std::vector< std::pair > OffsetVector; IndexedMzMLDecoder::OffsetVector spectra_offsets, chromatograms_offsets; - int res = IndexedMzMLDecoder().parseOffsets(filename, index_offset_, spectra_offsets, chromatograms_offsets); + int res = IndexedMzMLDecoder().parseOffsets(filename_, index_offset_, spectra_offsets, chromatograms_offsets); for (const auto& off : spectra_offsets) { spectra_native_ids_.emplace(off.first, spectra_offsets_.size()); @@ -80,8 +80,7 @@ namespace Internal else spectra_before_chroms_ = false; } - if (res == 0) parsing_success_ = true; - else parsing_success_ = false; + parsing_success_ = (res == 0); } IndexedMzMLHandler::IndexedMzMLHandler(const String& filename) : @@ -114,15 +113,15 @@ namespace Internal { } - void IndexedMzMLHandler::openFile(String filename) + void IndexedMzMLHandler::openFile(const String& filename) { - if (filestream_.is_open()) + if (filestream_.is_open()) // important; otherwise opening again will fail { filestream_.close(); } filename_ = filename; - filestream_.open(filename.c_str()); - parseFooter_(filename); + filestream_.open(filename); + parseFooter_(); } bool IndexedMzMLHandler::getParsingSuccess() const @@ -306,16 +305,16 @@ namespace Internal return c; } - void IndexedMzMLHandler::getMSChromatogramByNativeId(std::string id, OpenMS::MSChromatogram& c) + void IndexedMzMLHandler::getMSChromatogramByNativeId(const std::string& id, OpenMS::MSChromatogram& c) { - if (chromatograms_native_ids_.find(id) == chromatograms_native_ids_.end()) + auto it = chromatograms_native_ids_.find(id); + if (it == chromatograms_native_ids_.end()) { throw Exception::IllegalArgument(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, - String( "Could not find chromatogram id " + String(id) )); + String("Could not find chromatogram id ") + id ); } - getMSChromatogramById(chromatograms_native_ids_[id], c); + getMSChromatogramById(it->second, c); } - // const OpenMS::MSChromatogram IndexedMzMLHandler::getMSChromatogramById(int id) void IndexedMzMLHandler::getMSChromatogramById(int id, MSChromatogram& c) { diff --git a/src/openms/source/FORMAT/HANDLERS/MzIdentMLHandler.cpp b/src/openms/source/FORMAT/HANDLERS/MzIdentMLHandler.cpp index ede504f114b..bd8dd702501 100644 --- a/src/openms/source/FORMAT/HANDLERS/MzIdentMLHandler.cpp +++ b/src/openms/source/FORMAT/HANDLERS/MzIdentMLHandler.cpp @@ -1088,7 +1088,7 @@ namespace OpenMS kt != annotations.end(); ++kt) {// string coding example: [alpha|ci$y3-H2O-NH3]5+ // static const boost::regex frag_regex("\\[(?:([\\|\\w]+)\\$)*([abcxyz])(\\d+)((?:[\\+\\-\\w])*)\\](\\d+)\\+"); // this will fetch the complete loss/gain part as one - static const boost::regex frag_regex_tweak("\\[(?:([\\|\\w]+)\\$)*([abcxyz])(\\d+)(?:-(H2O|NH3))*\\][(\\d+)\\+]*"); // this will only fetch the last loss - and is preferred for now, as only these extra cv params are present + static const boost::regex frag_regex_tweak(R"(\[(?:([\|\w]+)\$)*([abcxyz])(\d+)(?:-(H2O|NH3))*\][(\d+)\+]*)"); // this will only fetch the last loss - and is preferred for now, as only these extra cv params are present String ionseries_index; String iontype; //String loss_gain; diff --git a/src/openms/source/FORMAT/HANDLERS/ParamXMLHandler.cpp b/src/openms/source/FORMAT/HANDLERS/ParamXMLHandler.cpp index 26ae86382f9..ba57d077fdb 100644 --- a/src/openms/source/FORMAT/HANDLERS/ParamXMLHandler.cpp +++ b/src/openms/source/FORMAT/HANDLERS/ParamXMLHandler.cpp @@ -74,7 +74,7 @@ namespace OpenMS //tags String tags_string; optionalAttributeAsString_(tags_string, attributes, "tags"); - StringList tags = ListUtils::create(tags_string); + std::vector tags = ListUtils::create(tags_string); //advanced String advanced_string; @@ -161,7 +161,7 @@ namespace OpenMS else if (type == "string") { val.split(',', parts); - param_.setValidStrings(name, parts); + param_.setValidStrings(name, ListUtils::create(parts)); } else if (type == "float" || type == "double") { @@ -198,7 +198,7 @@ namespace OpenMS std::vector parts; val.split(',', parts); - param_.setValidStrings(name, parts); + param_.setValidStrings(name, ListUtils::create(parts)); } } @@ -223,7 +223,7 @@ namespace OpenMS //tags String tags_string; optionalAttributeAsString_(tags_string, attributes, "tags"); - list_.tags = ListUtils::create(tags_string); + list_.tags = ListUtils::create(tags_string); //parse name/type @@ -338,7 +338,7 @@ namespace OpenMS if (list_.restrictions_index != -1) { list_.restrictions.split(',', parts); - param_.setValidStrings(list_.name, parts); + param_.setValidStrings(list_.name, ListUtils::create(parts)); } } else if (list_.type == "int") diff --git a/src/openms/source/FORMAT/MSPFile.cpp b/src/openms/source/FORMAT/MSPFile.cpp index 646ed5297eb..f1d0d141ac3 100644 --- a/src/openms/source/FORMAT/MSPFile.cpp +++ b/src/openms/source/FORMAT/MSPFile.cpp @@ -49,14 +49,14 @@ namespace OpenMS DefaultParamHandler("MSPFile") { defaults_.setValue("parse_headers", "false", "Flag whether header information should be parsed an stored for each spectrum"); - vector parse_strings{"true","false"}; + vector parse_strings{"true","false"}; defaults_.setValidStrings("parse_headers", parse_strings); defaults_.setValue("parse_peakinfo", "true", "Flag whether the peak annotation information should be parsed and stored for each peak"); defaults_.setValidStrings("parse_peakinfo", parse_strings); defaults_.setValue("parse_firstpeakinfo_only", "true", "Flag whether only the first (default for 1:1 correspondence in SpecLibSearcher) or all peak annotation information should be parsed and stored for each peak."); defaults_.setValidStrings("parse_firstpeakinfo_only", parse_strings); defaults_.setValue("instrument", "", "If instrument given, only spectra of these type of instrument (Inst= in header) are parsed"); - defaults_.setValidStrings("instrument", ListUtils::create(",it,qtof,toftof")); + defaults_.setValidStrings("instrument", {"","it","qtof","toftof"}); defaultsToParam_(); } @@ -90,7 +90,7 @@ namespace OpenMS // matches 2+ whitespaces or tabs or returns " ", "\t", "\r" // Note: this is a hack because one of the encountered formats has single whitespaces in quotes. // TODO choose a format during construction of the class. If we actually knew how to call and define them. - const std::regex ws_rex("\\s{2,}|\\t|\\r"); + const std::regex ws_rex(R"(\s{2,}|\t|\r)"); exp.reset(); @@ -110,7 +110,7 @@ namespace OpenMS bool parse_headers(param_.getValue("parse_headers").toBool()); bool parse_peakinfo(param_.getValue("parse_peakinfo").toBool()); bool parse_firstpeakinfo_only(param_.getValue("parse_firstpeakinfo_only").toBool()); - String instrument((String)param_.getValue("instrument")); + std::string instrument((std::string)param_.getValue("instrument")); bool inst_type_correct(true); [[maybe_unused]] bool spectrast_format(false); // TODO: implement usage Size spectrum_number = 0; diff --git a/src/openms/source/FORMAT/MSPGenericFile.cpp b/src/openms/source/FORMAT/MSPGenericFile.cpp index 4d88c7fd576..af882a3298c 100644 --- a/src/openms/source/FORMAT/MSPGenericFile.cpp +++ b/src/openms/source/FORMAT/MSPGenericFile.cpp @@ -64,7 +64,7 @@ namespace OpenMS void MSPGenericFile::updateMembers_() { - synonyms_separator_ = (String)param_.getValue("synonyms_separator"); + synonyms_separator_ = param_.getValue("synonyms_separator").toString(); } void MSPGenericFile::load(const String& filename, MSExperiment& library) @@ -85,9 +85,9 @@ namespace OpenMS boost::cmatch m; boost::regex re_name("^Name: (.+)", boost::regex::no_mod_s); boost::regex re_synon("^synon(?:yms?)?: (.+)", boost::regex::no_mod_s | boost::regex::icase); - boost::regex re_points_line("^\\d"); - boost::regex re_point("(\\d+(?:\\.\\d+)?)[: ](\\d+(?:\\.\\d+)?);? ?"); - boost::regex re_cas_nist("^CAS#: ([\\d-]+); NIST#: (\\d+)"); // specific to NIST db + boost::regex re_points_line(R"(^\d)"); + boost::regex re_point(R"((\d+(?:\.\d+)?)[: ](\d+(?:\.\d+)?);? ?)"); + boost::regex re_cas_nist(R"(^CAS#: ([\d-]+); NIST#: (\d+))"); // specific to NIST db boost::regex re_metadatum("^(.+): (.+)", boost::regex::no_mod_s); OPENMS_LOG_INFO << "\nLoading spectra from .msp file. Please wait." << std::endl; @@ -160,7 +160,7 @@ namespace OpenMS throw Exception::MissingInformation(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "The current spectrum misses the Name information."); } - output_file << "Name: " << spectrum.getName() << std::endl; + output_file << "Name: " << spectrum.getName() << '\n'; const auto& synonyms = spectrum.getMetaValue("Synon"); if (synonyms.valueType() == OpenMS::DataValue::DataType::STRING_VALUE) { @@ -171,12 +171,12 @@ namespace OpenMS while ((start = synonyms_str.find_first_not_of(separator, end)) != std::string::npos) { end = synonyms_str.find(separator, start); - output_file << "Synon: " << synonyms_str.substr(start, end - start) << std::endl; + output_file << "Synon: " << synonyms_str.substr(start, end - start) << '\n'; } } if (spectrum.metaValueExists("CAS#") && spectrum.metaValueExists("NIST#")) { - output_file << "CAS#: " << spectrum.getMetaValue("CAS#") << "; NIST#: " << spectrum.getMetaValue("NIST#") << std::endl; + output_file << "CAS#: " << spectrum.getMetaValue("CAS#") << "; NIST#: " << spectrum.getMetaValue("NIST#") << '\n'; } // Other metadata const std::vector ignore_metadata = { "Synon", "CAS#", "NIST#", "Num Peaks" }; @@ -187,23 +187,22 @@ namespace OpenMS const auto& value = spectrum.getMetaValue(key); if (std::find(ignore_metadata.begin(), ignore_metadata.end(), key) == ignore_metadata.end()) { - output_file << key << ": " << value << std::endl; + output_file << key << ": " << value << '\n'; } } // Peaks - output_file << "Num Peaks: " << spectrum.size() << std::endl; + output_file << "Num Peaks: " << spectrum.size() << '\n'; int peak_counter = 0; for (const auto& peak : spectrum) { output_file << peak.getPos() << ":" << peak.getIntensity() << " "; - if ((++peak_counter % 5) == 0) output_file << std::endl; + if ((++peak_counter % 5) == 0) output_file << '\n'; } - if ((peak_counter % 5) != 0) output_file << std::endl; + if ((peak_counter % 5) != 0) output_file << '\n'; // separator - output_file << std::endl; + output_file << '\n'; } - output_file.flush(); output_file.close(); } @@ -256,6 +255,11 @@ namespace OpenMS } spectrum.removeMetaValue("is_valid"); + if (spectrum.getRT() < 0) + { // set RT to spectrum index + spectrum.setRT(library.getSpectra().size()); + } + library.addSpectrum(spectrum); loaded_spectra_names_.insert(spectrum.getName()); diff --git a/src/openms/source/FORMAT/MascotGenericFile.cpp b/src/openms/source/FORMAT/MascotGenericFile.cpp index 6e9555cabae..20aa80113b0 100644 --- a/src/openms/source/FORMAT/MascotGenericFile.cpp +++ b/src/openms/source/FORMAT/MascotGenericFile.cpp @@ -60,8 +60,8 @@ namespace OpenMS ProgressLogger(), DefaultParamHandler("MascotGenericFile"), mod_group_map_() { defaults_.setValue("database", "MSDB", "Name of the sequence database"); - defaults_.setValue("search_type", "MIS", "Name of the search type for the query", ListUtils::create("advanced")); - defaults_.setValidStrings("search_type", ListUtils::create("MIS,SQ,PMF")); + defaults_.setValue("search_type", "MIS", "Name of the search type for the query", {"advanced"}); + defaults_.setValidStrings("search_type", {"MIS","SQ","PMF"}); defaults_.setValue("enzyme", "Trypsin", "The enzyme descriptor to the enzyme used for digestion. (Trypsin is default, None would be best for peptide input or unspecific digestion, for more please refer to your mascot server)."); defaults_.setValue("instrument", "Default", "Instrument definition which specifies the fragmentation rules"); defaults_.setValue("missed_cleavages", 1, "Number of missed cleavages allowed for the enzyme"); @@ -69,47 +69,48 @@ namespace OpenMS defaults_.setValue("precursor_mass_tolerance", 3.0, "Tolerance of the precursor peaks"); defaults_.setMinFloat("precursor_mass_tolerance", 0.0); defaults_.setValue("precursor_error_units", "Da", "Units of the precursor mass tolerance"); - defaults_.setValidStrings("precursor_error_units", ListUtils::create("%,ppm,mmu,Da")); + defaults_.setValidStrings("precursor_error_units", {"%","ppm","mmu","Da"}); defaults_.setValue("fragment_mass_tolerance", 0.3, "Tolerance of the peaks in the fragment spectrum"); defaults_.setMinFloat("fragment_mass_tolerance", 0.0); defaults_.setValue("fragment_error_units", "Da", "Units of the fragment peaks tolerance"); - defaults_.setValidStrings("fragment_error_units", ListUtils::create("mmu,Da")); + defaults_.setValidStrings("fragment_error_units", {"mmu","Da"}); defaults_.setValue("charges", "1,2,3", "Charge states to consider, given as a comma separated list of integers (only used for spectra without precursor charge information)"); defaults_.setValue("taxonomy", "All entries", "Taxonomy specification of the sequences"); vector all_mods; ModificationsDB::getInstance()->getAllSearchModifications(all_mods); - defaults_.setValue("fixed_modifications", ListUtils::create(""), "List of fixed modifications, according to UniMod definitions."); - defaults_.setValidStrings("fixed_modifications", all_mods); - defaults_.setValue("variable_modifications", ListUtils::create(""), "Variable modifications given as UniMod definitions."); - defaults_.setValidStrings("variable_modifications", all_mods); + + defaults_.setValue("fixed_modifications", std::vector(), "List of fixed modifications, according to UniMod definitions."); + defaults_.setValidStrings("fixed_modifications", ListUtils::create(all_mods)); + defaults_.setValue("variable_modifications", std::vector(), "Variable modifications given as UniMod definitions."); + defaults_.setValidStrings("variable_modifications", ListUtils::create(all_mods)); // special modifications, see "updateMembers_" method below: - defaults_.setValue("special_modifications", "Cation:Na (DE),Deamidated (NQ),Oxidation (HW),Phospho (ST),Sulfo (ST)", "Modifications with specificity groups that are used by Mascot and have to be treated specially", ListUtils::create("advanced")); + defaults_.setValue("special_modifications", "Cation:Na (DE),Deamidated (NQ),Oxidation (HW),Phospho (ST),Sulfo (ST)", "Modifications with specificity groups that are used by Mascot and have to be treated specially", {"advanced"}); // list from Mascot 2.4; there's also "Phospho (STY)", but that can be // represented using "Phospho (ST)" and "Phospho (Y)" defaults_.setValue("mass_type", "monoisotopic", "Defines the mass type, either monoisotopic or average"); - defaults_.setValidStrings("mass_type", ListUtils::create("monoisotopic,average")); + defaults_.setValidStrings("mass_type", {"monoisotopic","average"}); defaults_.setValue("number_of_hits", 0, "Number of hits which should be returned, if 0 AUTO mode is enabled."); defaults_.setMinInt("number_of_hits", 0); defaults_.setValue("skip_spectrum_charges", "false", "Sometimes precursor charges are given for each spectrum but are wrong, setting this to 'true' does not write any charge information to the spectrum, the general charge information is however kept."); - defaults_.setValidStrings("skip_spectrum_charges", ListUtils::create("true,false")); + defaults_.setValidStrings("skip_spectrum_charges", {"true","false"}); defaults_.setValue("decoy", "false", "Set to true if mascot should generate the decoy database."); - defaults_.setValidStrings("decoy", ListUtils::create("true,false")); + defaults_.setValidStrings("decoy", {"true","false"}); - defaults_.setValue("search_title", "OpenMS_search", "Sets the title of the search.", ListUtils::create("advanced")); - defaults_.setValue("username", "OpenMS", "Sets the username which is mentioned in the results file.", ListUtils::create("advanced")); + defaults_.setValue("search_title", "OpenMS_search", "Sets the title of the search.", {"advanced"}); + defaults_.setValue("username", "OpenMS", "Sets the username which is mentioned in the results file.", {"advanced"}); defaults_.setValue("email", "", "Sets the email which is mentioned in the results file. Note: Some server require that a proper email is provided."); // the next section should not be shown to TOPP users Param p; - p.setValue("format", "Mascot generic", "Sets the format type of the peak list, this should not be changed unless you write the header only.", ListUtils::create("advanced")); - p.setValidStrings("format", ListUtils::create("Mascot generic,mzData (.XML),mzML (.mzML)")); // Mascot's HTTP interface supports more, but we don't :) - p.setValue("boundary", "GZWgAaYKjHFeUaLOLEIOMq", "MIME boundary for parameter header (if using HTTP format)", ListUtils::create("advanced")); - p.setValue("HTTP_format", "false", "Write header with MIME boundaries instead of simple key-value pairs. For HTTP submission only.", ListUtils::create("advanced")); - p.setValidStrings("HTTP_format", ListUtils::create("true,false")); - p.setValue("content", "all", "Use parameter header + the peak lists with BEGIN IONS... or only one of them.", ListUtils::create("advanced")); - p.setValidStrings("content", ListUtils::create("all,peaklist_only,header_only")); + p.setValue("format", "Mascot generic", "Sets the format type of the peak list, this should not be changed unless you write the header only.", {"advanced"}); + p.setValidStrings("format", {"Mascot generic","mzData (.XML)","mzML (.mzML)"}); // Mascot's HTTP interface supports more, but we don't :) + p.setValue("boundary", "GZWgAaYKjHFeUaLOLEIOMq", "MIME boundary for parameter header (if using HTTP format)", {"advanced"}); + p.setValue("HTTP_format", "false", "Write header with MIME boundaries instead of simple key-value pairs. For HTTP submission only.", {"advanced"}); + p.setValidStrings("HTTP_format", {"true","false"}); + p.setValue("content", "all", "Use parameter header + the peak lists with BEGIN IONS... or only one of them.", {"advanced"}); + p.setValidStrings("content", {"all","peaklist_only","header_only"}); defaults_.insert("internal:", p); defaultsToParam_(); @@ -123,7 +124,7 @@ namespace OpenMS { // special cases for specificity groups: OpenMS uses e.g. "Deamidated (N)" // and "Deamidated (Q)", but Mascot only understands "Deamidated (NQ)" - String special_mods = param_.getValue("special_modifications"); + String special_mods = param_.getValue("special_modifications").toString(); vector mod_groups = ListUtils::create(special_mods); for (StringList::const_iterator mod_it = mod_groups.begin(); mod_it != mod_groups.end(); ++mod_it) @@ -282,11 +283,11 @@ namespace OpenMS os << param_.getValue("mass_type") << "\n"; // fixed modifications - vector fixed_mods = param_.getValue("fixed_modifications"); + StringList fixed_mods = ListUtils::toStringList(param_.getValue("fixed_modifications")); writeModifications_(fixed_mods, os); // variable modifications - vector var_mods = param_.getValue("variable_modifications"); + StringList var_mods = ListUtils::toStringList(param_.getValue("variable_modifications")); writeModifications_(var_mods, os, true); // instrument @@ -431,8 +432,8 @@ namespace OpenMS std::pair MascotGenericFile::getHTTPPeakListEnclosure(const String& filename) const { std::pair r; - r.first = String("--" + String(param_.getValue("internal:boundary")) + "\n" + "Content-Disposition: form-data; name=\"FILE\"; filename=\"" + filename + "\"\n\n"); - r.second = String("\n\n--" + String(param_.getValue("internal:boundary")) + "--\n"); + r.first = String("--" + (std::string)param_.getValue("internal:boundary") + "\n" + "Content-Disposition: form-data; name=\"FILE\"; filename=\"" + filename + "\"\n\n"); + r.second = String("\n\n--" + (std::string)param_.getValue("internal:boundary") + "--\n"); return r; } diff --git a/src/openms/source/FORMAT/MascotRemoteQuery.cpp b/src/openms/source/FORMAT/MascotRemoteQuery.cpp index f0d8498cbf5..c920300ebfd 100644 --- a/src/openms/source/FORMAT/MascotRemoteQuery.cpp +++ b/src/openms/source/FORMAT/MascotRemoteQuery.cpp @@ -62,30 +62,30 @@ namespace OpenMS "This is NOT the whole time the search takes, but the time in between two progress steps. Some Mascot servers freeze during this (unstable network etc) and idle forever" ", the connection is killed. Set this to 0 to disable timeout!"); defaults_.setMinInt("timeout", 0); - defaults_.setValue("boundary", "GZWgAaYKjHFeUaLOLEIOMq", "Boundary for the MIME section", ListUtils::create("advanced")); + defaults_.setValue("boundary", "GZWgAaYKjHFeUaLOLEIOMq", "Boundary for the MIME section", {"advanced"}); // proxy settings - defaults_.setValue("use_proxy", "false", "Flag which enables the proxy usage for the HTTP requests, please specify at least 'proxy_host' and 'proxy_port'", ListUtils::create("advanced")); - defaults_.setValidStrings("use_proxy", ListUtils::create("true,false")); - defaults_.setValue("proxy_host", "", "Host where the proxy server runs on", ListUtils::create("advanced")); - defaults_.setValue("proxy_port", 0, "Port where the proxy server listens", ListUtils::create("advanced")); + defaults_.setValue("use_proxy", "false", "Flag which enables the proxy usage for the HTTP requests, please specify at least 'proxy_host' and 'proxy_port'", {"advanced"}); + defaults_.setValidStrings("use_proxy", {"true","false"}); + defaults_.setValue("proxy_host", "", "Host where the proxy server runs on", {"advanced"}); + defaults_.setValue("proxy_port", 0, "Port where the proxy server listens", {"advanced"}); defaults_.setMinInt("proxy_port", 0); - defaults_.setValue("proxy_username", "", "Login name for the proxy server, if needed", ListUtils::create("advanced")); - defaults_.setValue("proxy_password", "", "Login password for the proxy server, if needed", ListUtils::create("advanced")); + defaults_.setValue("proxy_username", "", "Login name for the proxy server, if needed", {"advanced"}); + defaults_.setValue("proxy_password", "", "Login password for the proxy server, if needed", {"advanced"}); // login for Mascot security defaults_.setValue("login", "false", "Flag which should be set 'true' if Mascot security is enabled; also set 'username' and 'password' then."); - defaults_.setValidStrings("login", ListUtils::create("true,false")); + defaults_.setValidStrings("login", {"true","false"}); defaults_.setValue("username", "", "Name of the user if login is used (Mascot security must be enabled!)"); defaults_.setValue("password", "", "Password of the user if login is used (Mascot security must be enabled!)"); defaults_.setValue("use_ssl", "false", "Flag indicating whether you want to send requests to an HTTPS server or not (HTTP). Requires OpenSSL to be installed (see openssl.org)"); - defaults_.setValidStrings("use_ssl", ListUtils::create("true,false")); + defaults_.setValidStrings("use_ssl", {"true","false"}); // Mascot export options - defaults_.setValue("export_params", "_ignoreionsscorebelow=0&_sigthreshold=0.99&_showsubsets=1&show_same_sets=1&report=0&percolate=0&query_master=0", "Adjustable export parameters (passed to Mascot's 'export_dat_2.pl' script). Generally only parameters that control which hits to export are safe to adjust/add. Many settings that govern what types of information to include are required by OpenMS and cannot be changed. Note that setting 'query_master' to 1 may lead to incorrect protein references for peptides.", ListUtils::create("advanced")); - defaults_.setValue("skip_export", "false", "For use with an external Mascot Percolator (via GenericWrapper): Run the Mascot search, but do not export the results. The output file produced by MascotAdapterOnline will contain only the Mascot search number.", ListUtils::create("advanced")); - defaults_.setValidStrings("skip_export", ListUtils::create("true,false")); - defaults_.setValue("batch_size", 50000, "Number of spectra processed in one batch by Mascot (default 50000)", ListUtils::create("advanced")); + defaults_.setValue("export_params", "_ignoreionsscorebelow=0&_sigthreshold=0.99&_showsubsets=1&show_same_sets=1&report=0&percolate=0&query_master=0", "Adjustable export parameters (passed to Mascot's 'export_dat_2.pl' script). Generally only parameters that control which hits to export are safe to adjust/add. Many settings that govern what types of information to include are required by OpenMS and cannot be changed. Note that setting 'query_master' to 1 may lead to incorrect protein references for peptides.", {"advanced"}); + defaults_.setValue("skip_export", "false", "For use with an external Mascot Percolator (via GenericWrapper): Run the Mascot search, but do not export the results. The output file produced by MascotAdapterOnline will contain only the Mascot search number.", {"advanced"}); + defaults_.setValidStrings("skip_export", {"true","false"}); + defaults_.setValue("batch_size", 50000, "Number of spectra processed in one batch by Mascot (default 50000)", {"advanced"}); defaults_.setMinInt("batch_size", 0); defaultsToParam_(); } @@ -185,13 +185,13 @@ namespace OpenMS loginbytes.append("Content-Disposition: "); loginbytes.append("form-data; name=\"username\"\r\n"); loginbytes.append("\r\n"); - loginbytes.append(((String)param_.getValue("username")).c_str()); + loginbytes.append(String(param_.getValue("username").toString()).toQString()); loginbytes.append("\r\n"); loginbytes.append(boundary_string); loginbytes.append("Content-Disposition: "); loginbytes.append("form-data; name=\"password\"\r\n"); loginbytes.append("\r\n"); - loginbytes.append(((String)param_.getValue("password")).c_str()); + loginbytes.append(String(param_.getValue("password").toString()).toQString()); loginbytes.append("\r\n"); loginbytes.append(boundary_string); loginbytes.append("Content-Disposition: "); @@ -584,7 +584,7 @@ namespace OpenMS // see http://www.matrixscience.com/help/export_help.html for parameter documentation String required_params = "&do_export=1&export_format=XML&generate_file=1&group_family=1&peptide_master=1&protein_master=1&search_master=1&show_unassigned=1&show_mods=1&show_header=1&show_params=1&prot_score=1&pep_exp_z=1&pep_score=1&pep_seq=1&pep_homol=1&pep_ident=1&pep_expect=1&pep_var_mod=1&pep_scan_title=1&query_qualifiers=1&query_peaks=1&query_raw=1&query_title=1"; // TODO: check that export_params don't contain _show_decoy_report=1. This would add at the top of the XML document and we can't easily distinguish the two files (target/decoy) from the search results later. - String adjustable_params = param_.getValue("export_params"); + String adjustable_params = param_.getValue("export_params").toString(); results_path.append(required_params.toQString() + "&" + adjustable_params.toQString()); @@ -620,7 +620,7 @@ namespace OpenMS { // check whether Mascot responded using an error code e.g. [M00440], pipe through results else QString response_text = new_bytes; - QRegExp mascot_error_regex("\\[M[0-9][0-9][0-9][0-9][0-9]\\]"); + QRegExp mascot_error_regex(R"(\[M[0-9][0-9][0-9][0-9][0-9]\])"); if (response_text.contains(mascot_error_regex)) { OPENMS_LOG_ERROR << "Received response with Mascot error message!" << std::endl; @@ -662,7 +662,7 @@ namespace OpenMS // see http://www.matrixscience.com/help/export_help.html for parameter documentation String required_params = "&do_export=1&export_format=XML&generate_file=1&group_family=1&peptide_master=1&protein_master=1&search_master=1&show_unassigned=1&show_mods=1&show_header=1&show_params=1&prot_score=1&pep_exp_z=1&pep_score=1&pep_seq=1&pep_homol=1&pep_ident=1&pep_expect=1&pep_var_mod=1&pep_scan_title=1&query_qualifiers=1&query_peaks=1&query_raw=1&query_title=1"; // TODO: check that export_params don't contain _show_decoy_report=1. This would add at the top of the XML document and we can't easily distinguish the two files (target/decoy) from the search results later. - String adjustable_params = param_.getValue("export_params"); + String adjustable_params = param_.getValue("export_params").toString(); results_path.append(required_params.toQString() + "&" + adjustable_params.toQString() + "&_show_decoy_report=1&show_decoy=1"); // request @@ -717,12 +717,12 @@ namespace OpenMS #ifdef MASCOTREMOTEQUERY_DEBUG cerr << "MascotRemoteQuery::updateMembers_()" << "\n"; #endif - server_path_ = param_.getValue("server_path"); + server_path_ = param_.getValue("server_path").toString(); //MascotRemoteQuery_test if (server_path_ != "") server_path_ = "/" + server_path_; - host_name_ = param_.getValue("hostname"); + host_name_ = param_.getValue("hostname").toString(); use_ssl_ = param_.getValue("use_ssl").toBool(); #ifndef QT_NO_SSL @@ -739,7 +739,7 @@ namespace OpenMS } #endif - boundary_ = param_.getValue("boundary"); + boundary_ = param_.getValue("boundary").toString(); cookie_ = ""; mascot_xml_ = ""; mascot_decoy_xml_ = ""; @@ -753,15 +753,15 @@ namespace OpenMS { QNetworkProxy proxy; proxy.setType(QNetworkProxy::Socks5Proxy); - String proxy_host(param_.getValue("proxy_host")); + String proxy_host(param_.getValue("proxy_host").toString()); proxy.setHostName(proxy_host.toQString()); - String proxy_port(param_.getValue("proxy_port")); + String proxy_port(param_.getValue("proxy_port").toString()); proxy.setPort(proxy_port.toInt()); - String proxy_password(param_.getValue("proxy_password")); + String proxy_password(param_.getValue("proxy_password").toString()); proxy.setPassword(proxy_password.toQString()); - String proxy_username(param_.getValue("proxy_username")); + String proxy_username(param_.getValue("proxy_username").toString()); if (proxy_username != "") { proxy.setUser(proxy_username.toQString()); diff --git a/src/openms/source/FORMAT/MzQCFile.cpp b/src/openms/source/FORMAT/MzQCFile.cpp index 0f23d1e7d42..77c27d1c181 100644 --- a/src/openms/source/FORMAT/MzQCFile.cpp +++ b/src/openms/source/FORMAT/MzQCFile.cpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include @@ -53,97 +55,43 @@ using namespace std; namespace OpenMS { - void MzQCFile::store(const String & inputFileName, - const String & outputFileName, - const MSExperiment & exp, - const String & contactName, - const String & contactAddress, - const String & description, - const String & label) const + void MzQCFile::store(const String& input_file, + const String& output_file, + const MSExperiment& exp, + const String& contact_name, + const String& contact_address, + const String& description, + const String& label) const { - using json = nlohmann::ordered_json; - json out; - // required: creationDate, version - DateTime currentTime = DateTime::now(); - out["mzQC"]["creationDate"] = currentTime.toString(); - out["mzQC"]["version"] = "1.0.0"; - - // optional: contactName, contactAddress, description - if (!contactName.empty()) - { - out["mzQC"]["contactName"] = contactName; - } - if (!contactAddress.empty()) - { - out["mzQC"]["contactAddress"] = contactAddress; - } - if (!description.empty()) + // -------------------------------------------------------------------- + // preparing output stream, quality metrics json object, CV, status + // and initialize QC metric classes + // -------------------------------------------------------------------- + ofstream os(output_file.c_str()); + if (!os) { - out["mzQC"]["description"] = description; + throw Exception::UnableToCreateFile(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, output_file); } - out["mzQC"]["runQualities"]["metadata"]["label"] = label; - out["mzQC"]["runQualities"]["metadata"]["inputFiles"] = { - { - {"location", File::absolutePath(inputFileName)}, - {"name", File::basename(inputFileName)}, - {"fileFormat", - { - {"accession", "MS:10000584"}, - {"name", "mzML format"} - } - } - }, - "fileProperties", - { - { - {"accession", "MS:1000747"}, - {"name", "completion time"}, - {"value", String(exp.getDateTime().getDate() + "T" + exp.getDateTime().getTime())} - }, - { - {"accession", "MS:1000569"}, - {"name", "SHA-1"}, - {"value", String(FileHandler::computeFileHash(inputFileName))} - }, - { - {"accession", "MS:1000031"}, - {"name", "instrument model"}, - {"value", String(exp.getInstrument().getName())} - } - } - }; - - VersionInfo::VersionDetails version = VersionInfo::getVersionStruct(); - out["mzQC"]["runQualities"]["metadata"]["analysisSoftware"] = { // todo - { - {"accession", "MS:1009001" }, // create new qc-cv for QCCalculator: MS:1009001 quality control metrics generating software - {"name", "QCCalculator"}, - {"version", String(version.version_major)+"."+String(version.version_minor)+"."+String(version.version_patch)}, - {"uri", "https://www.openms.de"} - } - }; + using json = nlohmann::ordered_json; + json quality_metrics = {}; - out["mzQC"]["runQualities"]["qualityMetrics"] = {}; - - out["mzQC"]["controlledVocabularies"] = { - { - {"name", "Proteomics Standards Initiative Quality Control Ontology"}, - {"uri", "https://github.com/HUPO-PSI/mzQC/blob/master/cv/qc-cv.obo"}, - {"version", "0.1.2"}, - }, - { - {"name", "Proteomics Standards Initiative Mass Spectrometry Ontology"}, - {"uri", "https://github.com/HUPO-PSI/psi-ms-CV/blob/master/psi-ms.obo"}, - {"version", "4.1.49"} - } - }; ControlledVocabulary cv; cv.loadFromOBO("PSI-MS", File::find("/CV/psi-ms.obo")); cv.loadFromOBO("QC", File::find("/CV/qc-cv.obo")); - // create qualityMetric in json format - auto addValue = [&cv](const String& accession, const String& name, const auto& value) -> json + QCBase::Status status; + if (input_file != "") + { + status |= QCBase::Requires::RAWMZML; + } + TIC tic; + SpectrumCount spectrum_count; + + // --------------------------------------------------------------- + // function to add quality metrics to quality_metrics + // --------------------------------------------------------------- + auto addMetric = [&cv, &quality_metrics](const String& accession, const auto& value) -> void { json qm; qm["accession"] = accession; @@ -153,92 +101,143 @@ namespace OpenMS } else { - qm["name"] = name; cout << accession << " not found in CV." << endl; + return; } qm["value"] = value; - return qm; + quality_metrics.push_back(qm); }; - map counts; - for (const auto& spectrum : exp) - { - const Size level = spectrum.getMSLevel(); - ++counts[level]; // count MS level - } - // QC:4000059 Number of MS1 spectra - out["mzQC"]["runQualities"]["qualityMetrics"] += addValue("QC:4000059", "Number of MS1 spectra", counts[1]); - // QC:4000060 Number of MS2 spectra - out["mzQC"]["runQualities"]["qualityMetrics"] += addValue("QC:4000060", "Number of MS2 spectra", counts[2]); - // QC:4000135 Number of chromatograms" - out["mzQC"]["runQualities"]["qualityMetrics"] += addValue("QC:4000135", "Number of chromatograms", exp.getChromatograms().size()); - // QC:4000053 Run time (RT duration) - out["mzQC"]["runQualities"]["qualityMetrics"] += addValue("QC:4000053", "RT duration", UInt(exp.getMaxRT() - exp.getMinRT())); - // QC:4000138 MZ acquisition range - out["mzQC"]["runQualities"]["qualityMetrics"] += addValue("QC:4000138", "MZ acquisition range", tuple{exp.getMinMZ(), exp.getMaxMZ()}); - - const MSChromatogram& tic = exp.getTIC(); - UInt jump = 0; - UInt fall = 0; - vector retention_times; - vector intensities; - - for (const auto& p : tic) + // --------------------------------------------------------------- + // collecting quality metrics + // --------------------------------------------------------------- + + if (spectrum_count.isRunnable(status)) { - intensities.push_back(p.getIntensity()); - retention_times.push_back(p.getRT()); + auto counts = spectrum_count.compute(exp); + // Number of MS1 spectra + addMetric("QC:4000059", counts[1]); + // Number of MS2 spectra + addMetric("QC:4000060", counts[2]); } - - UInt tic_area = intensities[0]; - - for (UInt i = 1; i < intensities.size(); ++i) + // Number of chromatograms" + addMetric("QC:4000135", exp.getChromatograms().size()); + // Run time (RT duration) + addMetric("QC:4000053", UInt(exp.getMaxRT() - exp.getMinRT())); + // MZ acquisition range + addMetric("QC:4000138", tuple{exp.getMinMZ(), exp.getMaxMZ()}); + + if (tic.isRunnable(status)) { - tic_area += intensities[i]; - if (intensities[i] > intensities[i-1] * 10) // detect 10x jumps between two subsequent scans + auto result = tic.compute(exp); + if (!result.intensities.empty()) { - ++jump; - } - if (intensities[i] < intensities[i-1] / 10) // detect 10x falls between two subsequent scans - { - ++fall; + json chrom; + chrom["Relative intensity"] = result.intensities; + chrom["Retention time"] = result.retention_times; + // Total ion current chromatogram + addMetric("QC:4000067", chrom); + // Area under TIC + addMetric("QC:4000077", result.area); + // MS1 signal jump (10x) count + addMetric("QC:4000172", result.jump); + // MS1 signal fall (10x) count + addMetric("QC:4000173", result.fall); } } - - json tic_values; - tic_values["Relative intensity"] = intensities; - tic_values["Retention time"] = retention_times; - if (!tic.empty()) + // --------------------------------------------------------------- + // writing mzQC file + // --------------------------------------------------------------- + json out; + // required: creationDate, version + DateTime currentTime = DateTime::now(); + out["mzQC"]["creationDate"] = currentTime.toString(); + out["mzQC"]["version"] = "1.0.0"; + + // optional: contact_name, contact_address, description + if (!contact_name.empty()) { - // QC:4000067 Total ion current chromatogram - out["mzQC"]["runQualities"]["qualityMetrics"] += addValue("QC:4000067", "Total ion current chromatogram", tic_values); - // QC:4000077 Area under TIC - out["mzQC"]["runQualities"]["qualityMetrics"] += addValue("QC:4000077", "Area under TIC", tic_area); - // QC:4000172 MS1 signal jump (10x) count - out["mzQC"]["runQualities"]["qualityMetrics"] += addValue("QC:4000172", "MS1 signal jump (10x) count", jump); - // QC:4000173 MS1 signal fall (10x) count - out["mzQC"]["runQualities"]["qualityMetrics"] += addValue("QC:4000173", "MS1 signal fall (10x) count", fall); + out["mzQC"]["contactName"] = contact_name; } - - // QC:4000074 Median MS1 peak FWHM for peptides - // QC:4000257 Detected Compounds - // MS:1000005 sample volume - // MS:1000011 mass resolution - // MS:1000015 scan rate - // MS:1000026 detector type - - // HPLC: - // QC:4000107 Column type - // QC:4000079 Pump pressure chromatogram - - //open stream - ofstream os(outputFileName.c_str()); - if (!os) + if (!contact_address.empty()) { - throw Exception::UnableToCreateFile(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, outputFileName); + out["mzQC"]["contactAddress"] = contact_address; + } + if (!description.empty()) + { + out["mzQC"]["description"] = description; } + // get OpenMS version for runQualities + VersionInfo::VersionDetails version = VersionInfo::getVersionStruct(); + out["mzQC"]["runQualities"] = + { + { + {"metadata", + { + {"label", label}, + {"inputFiles", + { + { + {"location", File::absolutePath(input_file)}, + {"name", File::basename(input_file)}, + {"fileFormat", + { + {"accession", "MS:10000584"}, + {"name", "mzML format"} + } + }, + {"fileProperties", + { + { + {"accession", "MS:1000747"}, + {"name", "completion time"}, + {"value", String(exp.getDateTime().getDate() + "T" + exp.getDateTime().getTime())} + }, + { + {"accession", "MS:1000569"}, + {"name", "SHA-1"}, + {"value", String(FileHandler::computeFileHash(input_file))} + }, + { + {"accession", "MS:1000031"}, + {"name", "instrument model"}, + {"value", String(exp.getInstrument().getName())} + } + } + } + } + } + }, + {"analysisSoftware", + { + { + {"accession", "MS:1009001" }, // create new qc-cv for QCCalculator: MS:1009001 quality control metrics generating software + {"name", "QCCalculator"}, + {"version", String(version.version_major)+"."+String(version.version_minor)+"."+String(version.version_patch)}, + {"uri", "https://www.openms.de"} + } + } + } + } + }, + {"qualityMetrics", quality_metrics} + } + }; - // write out the json object in proper format with indentation level of 2 + out["mzQC"]["controlledVocabularies"] = + { + { + {"name", "Proteomics Standards Initiative Quality Control Ontology"}, + {"uri", "https://github.com/HUPO-PSI/mzQC/blob/master/cv/qc-cv.obo"}, + {"version", "0.1.2"}, + }, + { + {"name", "Proteomics Standards Initiative Mass Spectrometry Ontology"}, + {"uri", "https://github.com/HUPO-PSI/psi-ms-CV/blob/master/psi-ms.obo"}, + {"version", "4.1.49"} + } + }; os << out.dump(2); } diff --git a/src/openms/source/FORMAT/MzTabFile.cpp b/src/openms/source/FORMAT/MzTabFile.cpp index 81a1c7a3c1d..af3accee975 100644 --- a/src/openms/source/FORMAT/MzTabFile.cpp +++ b/src/openms/source/FORMAT/MzTabFile.cpp @@ -85,14 +85,14 @@ namespace OpenMS // $ # Match the end of the line boost::sregex_token_iterator end; - boost::regex rx_first_number("^.*?\\[(\\d+)\\].*$"); + boost::regex rx_first_number(R"(^.*?\[(\d+)\].*$)"); boost::sregex_token_iterator it1(s.begin(), s.end(), rx_first_number, 1); if (it1 != end) { pair.first = String(*it1++).toInt(); } - boost::regex rx_second_number("^.*?\\[\\d+\\].*?\\[(\\d+)\\].*$"); + boost::regex rx_second_number(R"(^.*?\[\d+\].*?\[(\d+)\].*$)"); boost::sregex_token_iterator it2(s.begin(), s.end(), rx_second_number, 1); if (it2 != end) { diff --git a/src/openms/source/FORMAT/ParamXMLFile.cpp b/src/openms/source/FORMAT/ParamXMLFile.cpp index 456f8e417ba..3575dcb27d7 100644 --- a/src/openms/source/FORMAT/ParamXMLFile.cpp +++ b/src/openms/source/FORMAT/ParamXMLFile.cpp @@ -116,26 +116,26 @@ namespace OpenMS } //write item - if (it->value.valueType() != DataValue::EMPTY_VALUE) + if (it->value.valueType() != ParamValue::EMPTY_VALUE) { // we create a temporary copy of the tag list, since we remove certain tags while writing, // that will be represented differently in the xml - std::set tag_list = it->tags; - DataValue::DataType value_type = it->value.valueType(); + std::set tag_list = it->tags; + ParamValue::ValueType value_type = it->value.valueType(); bool stringParamIsFlag = false; //write opening tag switch (value_type) { - case DataValue::INT_VALUE: + case ParamValue::INT_VALUE: os << indentation << "name) << "\" value=\"" << it->value.toString() << "\" type=\"int\""; break; - case DataValue::DOUBLE_VALUE: + case ParamValue::DOUBLE_VALUE: os << indentation << "name) << "\" value=\"" << it->value.toString() << "\" type=\"double\""; break; - case DataValue::STRING_VALUE: + case ParamValue::STRING_VALUE: if (tag_list.find("input file") != tag_list.end()) { os << indentation << "name) << "\" value=\"" << writeXMLEscape(it->value.toString()) << "\" type=\"input-file\""; @@ -159,7 +159,7 @@ namespace OpenMS } break; - case DataValue::STRING_LIST: + case ParamValue::STRING_LIST: if (tag_list.find("input file") != tag_list.end()) { os << indentation << "name) << "\" type=\"input-file\""; @@ -176,11 +176,11 @@ namespace OpenMS } break; - case DataValue::INT_LIST: + case ParamValue::INT_LIST: os << indentation << "name) << "\" type=\"int\""; break; - case DataValue::DOUBLE_LIST: + case ParamValue::DOUBLE_LIST: os << indentation << "name) << "\" type=\"double\""; break; @@ -222,7 +222,7 @@ namespace OpenMS if (!tag_list.empty()) { String list; - for (std::set::const_iterator tag_it = tag_list.begin(); tag_it != tag_list.end(); ++tag_it) + for (std::set::const_iterator tag_it = tag_list.begin(); tag_it != tag_list.end(); ++tag_it) { if (!list.empty()) list += ","; @@ -238,8 +238,8 @@ namespace OpenMS String restrictions = ""; switch (value_type) { - case DataValue::INT_VALUE: - case DataValue::INT_LIST: + case ParamValue::INT_VALUE: + case ParamValue::INT_LIST: { bool min_set = (it->min_int != -std::numeric_limits::max()); bool max_set = (it->max_int != std::numeric_limits::max()); @@ -258,8 +258,8 @@ namespace OpenMS } break; - case DataValue::DOUBLE_VALUE: - case DataValue::DOUBLE_LIST: + case ParamValue::DOUBLE_VALUE: + case ParamValue::DOUBLE_LIST: { bool min_set = (it->min_float != -std::numeric_limits::max()); bool max_set = (it->max_float != std::numeric_limits::max()); @@ -278,8 +278,8 @@ namespace OpenMS } break; - case DataValue::STRING_VALUE: - case DataValue::STRING_LIST: + case ParamValue::STRING_VALUE: + case ParamValue::STRING_LIST: if (it->valid_strings.size() != 0) { restrictions.concatenate(it->valid_strings.begin(), it->valid_strings.end(), ","); @@ -306,16 +306,16 @@ namespace OpenMS //finish opening tag switch (value_type) { - case DataValue::INT_VALUE: - case DataValue::DOUBLE_VALUE: - case DataValue::STRING_VALUE: + case ParamValue::INT_VALUE: + case ParamValue::DOUBLE_VALUE: + case ParamValue::STRING_VALUE: os << " />" << "\n"; break; - case DataValue::STRING_LIST: + case ParamValue::STRING_LIST: { os << ">" << "\n"; - const StringList& list = it->value; + const std::vector& list = it->value; for (Size i = 0; i < list.size(); ++i) { os << indentation << " " << "\n"; @@ -324,7 +324,7 @@ namespace OpenMS } break; - case DataValue::INT_LIST: + case ParamValue::INT_LIST: { os << ">" << "\n"; const IntList& list = it->value; @@ -336,7 +336,7 @@ namespace OpenMS } break; - case DataValue::DOUBLE_LIST: + case ParamValue::DOUBLE_LIST: { os << ">" << "\n"; const DoubleList& list = it->value; diff --git a/src/openms/source/FORMAT/QcMLFile.cpp b/src/openms/source/FORMAT/QcMLFile.cpp index 2fb11083d8b..ecbd5f3e01c 100644 --- a/src/openms/source/FORMAT/QcMLFile.cpp +++ b/src/openms/source/FORMAT/QcMLFile.cpp @@ -32,9 +32,8 @@ // $Authors: Mathias Walzer $ // -------------------------------------------------------------------------- -#include -#include +#include #include #include #include @@ -43,7 +42,9 @@ #include #include #include - +#include +#include +#include #include #include @@ -1928,7 +1929,6 @@ namespace OpenMS qp.name = "number of identified features"; ///< Name } addRunQualityParameter(base_name, qp); - } else if (inputfile_feature != "" && remove_duplicate_features) { @@ -2037,7 +2037,6 @@ namespace OpenMS void QcMLFile::store(const String& filename) const { - //~ startProgress(0, 0, "storing qcML file"); //~ progress_ = 0; //~ setProgress(++progress_); diff --git a/src/openms/source/FORMAT/TransformationXMLFile.cpp b/src/openms/source/FORMAT/TransformationXMLFile.cpp index 8ed88ab71b3..e7652e344c2 100644 --- a/src/openms/source/FORMAT/TransformationXMLFile.cpp +++ b/src/openms/source/FORMAT/TransformationXMLFile.cpp @@ -96,27 +96,27 @@ namespace OpenMS Param params = transformation.getModelParameters(); for (Param::ParamIterator it = params.begin(); it != params.end(); ++it) { - if (it->value.valueType() != DataValue::EMPTY_VALUE) + if (it->value.valueType() != ParamValue::EMPTY_VALUE) { switch (it->value.valueType()) { - case DataValue::INT_VALUE: + case ParamValue::INT_VALUE: os << "\t\tname << "\" value=\"" << it->value.toString() << "\"/>\n"; break; - case DataValue::DOUBLE_VALUE: + case ParamValue::DOUBLE_VALUE: os << "\t\tname << "\" value=\"" << it->value.toString() << "\"/>\n"; break; - case DataValue::STRING_VALUE: - case DataValue::STRING_LIST: - case DataValue::INT_LIST: - case DataValue::DOUBLE_LIST: + case ParamValue::STRING_VALUE: + case ParamValue::STRING_LIST: + case ParamValue::INT_LIST: + case ParamValue::DOUBLE_LIST: os << "\t\tname << "\" value=\"" << it->value.toString() << "\"/>\n"; break; default: // no other value types are supported! - fatalError(STORE, String("Unsupported parameter type of parameter '") + it->name + "' with value '" + it->value.toString() + "'"); + fatalError(STORE, String("Unsupported parameter type of parameter '") + it->name + "'"); break; } } diff --git a/src/openms/source/IONMOBILITY/FAIMSHelper.cpp b/src/openms/source/IONMOBILITY/FAIMSHelper.cpp new file mode 100644 index 00000000000..e7df72bbc6e --- /dev/null +++ b/src/openms/source/IONMOBILITY/FAIMSHelper.cpp @@ -0,0 +1,60 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: Eugen Netz $ +// $Authors: Eugen Netz $ +// -------------------------------------------------------------------------- + +#include +#include +#include + +namespace OpenMS +{ + std::set FAIMSHelper::getCompensationVoltages(const PeakMap& exp) + { + std::set CVs; + + // is this FAIMS data? + if ((exp.getSpectra().size() == 0) || + (exp.getSpectra()[0].getDriftTimeUnit() != MSSpectrum::DriftTimeUnit::FAIMS_COMPENSATION_VOLTAGE)) + { + return CVs; + } + + for (auto it = exp.begin(); it != exp.end(); ++it) + { + CVs.insert(it->getDriftTime()); + } + + return CVs; + } + +} //end namespace OpenMS diff --git a/src/openms/source/IONMOBILITY/MSRunIMSplitter.cpp b/src/openms/source/IONMOBILITY/MSRunIMSplitter.cpp new file mode 100644 index 00000000000..53b8cc05c8d --- /dev/null +++ b/src/openms/source/IONMOBILITY/MSRunIMSplitter.cpp @@ -0,0 +1,80 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: Eugen Netz $ +// $Authors: Eugen Netz $ +// -------------------------------------------------------------------------- + +#include +#include +#include +#include + +namespace OpenMS +{ + std::vector MSRunIMSplitter::splitByFAIMSCV(PeakMap&& exp) + { + std::vector split_peakmap; + + // TODO test with any random PeakMap without FAIMS data. + // What breaks, how should it break? + std::set CVs = FAIMSHelper::getCompensationVoltages(exp); + + if (CVs.empty()) + { + throw Exception::MissingInformation(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Not FAIMS data!"); + } + + // create map to easily turn a CV value into a PeakMap index + std::map cv2index; + size_t counter(0); + for (double cv : CVs) + { + cv2index[cv] = counter; + counter++; + } + + // make as many PeakMaps as there are different CVs and fill their Meta Data + split_peakmap.resize(CVs.size()); + for (auto it = split_peakmap.begin(); it != split_peakmap.end(); ++it) + { + it->getExperimentalSettings() = exp.getExperimentalSettings(); + } + + // fill up the PeakMaps by moving spectra from the input PeakMap + for (PeakMap::Iterator it = exp.begin(); it != exp.end(); ++it) + { + split_peakmap[cv2index[it->getDriftTime()]].addSpectrum(std::move(*it)); + } + + return split_peakmap; + } + +} //end namespace OpenMS diff --git a/src/openms/source/IONMOBILITY/sources.cmake b/src/openms/source/IONMOBILITY/sources.cmake new file mode 100644 index 00000000000..50c77d9c97b --- /dev/null +++ b/src/openms/source/IONMOBILITY/sources.cmake @@ -0,0 +1,20 @@ +### the directory name +set(directory source/IONMOBILITY) + +### list all filenames of the directory here +set(sources_list +FAIMSHelper.cpp +MSRunIMSplitter.cpp +) + +### add path to the filenames +set(sources) +foreach(i ${sources_list}) + list(APPEND sources ${directory}/${i}) +endforeach(i) + +### pass source file list to the upper instance +set(OpenMS_sources ${OpenMS_sources} ${sources}) + +### source group definition +source_group("Source Files\\IONMOBILITY" FILES ${sources}) diff --git a/src/openms/source/MATH/MISC/EmgGradientDescent.cpp b/src/openms/source/MATH/MISC/EmgGradientDescent.cpp index 7d7f769a6d7..16643717ef5 100644 --- a/src/openms/source/MATH/MISC/EmgGradientDescent.cpp +++ b/src/openms/source/MATH/MISC/EmgGradientDescent.cpp @@ -56,7 +56,7 @@ namespace OpenMS defaults.setMinInt("max_gd_iter", 0); defaults.setValue("compute_additional_points", "true", "Whether additional points should be added when fitting EMG peak model."); - defaults.setValidStrings("compute_additional_points", ListUtils::create("true,false")); + defaults.setValidStrings("compute_additional_points", {"true","false"}); } void EmgGradientDescent::updateMembers_() diff --git a/src/openms/source/MATH/STATISTICS/PosteriorErrorProbabilityModel.cpp b/src/openms/source/MATH/STATISTICS/PosteriorErrorProbabilityModel.cpp index 80b3b29052d..6d16518cb8c 100644 --- a/src/openms/source/MATH/STATISTICS/PosteriorErrorProbabilityModel.cpp +++ b/src/openms/source/MATH/STATISTICS/PosteriorErrorProbabilityModel.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -64,11 +64,11 @@ namespace OpenMS correctly_assigned_fit_param_(GaussFitter::GaussFitResult(-1, -1, -1)), negative_prior_(0.5), max_incorrectly_(0), max_correctly_(0), smallest_score_(0) { - defaults_.setValue("out_plot", "", "If given, the some output files will be saved in the following manner: _scores.txt for the scores and which contains the fitted values for each step of the EM-algorithm, e.g., out_plot = /usr/home/OMSSA123 leads to /usr/home/OMSSA123_scores.txt, /usr/home/OMSSA123 will be written. If no directory is specified, e.g. instead of '/usr/home/OMSSA123' just OMSSA123, the files will be written into the working directory.", ListUtils::create("advanced,output file")); - defaults_.setValue("number_of_bins", 100, "Number of bins used for visualization. Only needed if each iteration step of the EM-Algorithm will be visualized", ListUtils::create("advanced")); - defaults_.setValue("incorrectly_assigned", "Gumbel", "for 'Gumbel', the Gumbel distribution is used to plot incorrectly assigned sequences. For 'Gauss', the Gauss distribution is used.", ListUtils::create("advanced")); - defaults_.setValue("max_nr_iterations", 1000, "Bounds the number of iterations for the EM algorithm when convergence is slow.", ListUtils::create("advanced")); - defaults_.setValidStrings("incorrectly_assigned", ListUtils::create("Gumbel,Gauss")); + defaults_.setValue("out_plot", "", "If given, the some output files will be saved in the following manner: _scores.txt for the scores and which contains the fitted values for each step of the EM-algorithm, e.g., out_plot = /usr/home/OMSSA123 leads to /usr/home/OMSSA123_scores.txt, /usr/home/OMSSA123 will be written. If no directory is specified, e.g. instead of '/usr/home/OMSSA123' just OMSSA123, the files will be written into the working directory.", {"advanced","output file"}); + defaults_.setValue("number_of_bins", 100, "Number of bins used for visualization. Only needed if each iteration step of the EM-Algorithm will be visualized", {"advanced"}); + defaults_.setValue("incorrectly_assigned", "Gumbel", "for 'Gumbel', the Gumbel distribution is used to plot incorrectly assigned sequences. For 'Gauss', the Gauss distribution is used.", {"advanced"}); + defaults_.setValue("max_nr_iterations", 1000, "Bounds the number of iterations for the EM algorithm when convergence is slow.", {"advanced"}); + defaults_.setValidStrings("incorrectly_assigned", {"Gumbel","Gauss"}); defaults_.setValue("neg_log_delta",6, "The negative logarithm of the convergence threshold for the likelihood increase."); defaults_.setValue("outlier_handling","ignore_iqr_outliers", "What to do with outliers:\n" "- ignore_iqr_outliers: ignore outliers outside of 3*IQR from Q1/Q3 for fitting\n" @@ -117,12 +117,12 @@ namespace OpenMS //------------------------------------------------------------- // create files for output //------------------------------------------------------------- - bool output_plots = (param_.getValue("out_plot").toString().trim().length() > 0); + bool output_plots = (String(param_.getValue("out_plot").toString()).trim().length() > 0); TextFile file; if (output_plots) { // create output directory (if not already present) - QDir dir(param_.getValue("out_plot").toString().toQString()); + QDir dir(String(param_.getValue("out_plot").toString()).toQString()); if (!dir.cdUp()) { OPENMS_LOG_ERROR << "Could not navigate to output directory for plots from '" << String(dir.dirName()) << "'." << std::endl; @@ -233,7 +233,7 @@ namespace OpenMS formula2 = ((this)->*(getPositiveGnuplotFormula_))(correctly_assigned_fit_param_) + "* (1 - " + String(negative_prior_) + ")"; //String(correctly_assigned_fit_param_.A) +" * exp(-(x - " + String(correctly_assigned_fit_param_.x0) + ") ** 2 / 2 / (" + String(correctly_assigned_fit_param_.sigma) + ") ** 2)"+ "* (1 - " + String(negative_prior_) + ")"; formula3 = getBothGnuplotFormula(incorrectly_assigned_fit_param_, correctly_assigned_fit_param_); // important: use single quotes for paths, since otherwise backslashes will not be accepted on Windows! - file.addLine("plot '" + (String)param_.getValue("out_plot") + "_scores.txt' with boxes, " + formula1 + " , " + formula2 + " , " + formula3); + file.addLine("plot '" + (std::string)param_.getValue("out_plot") + "_scores.txt' with boxes, " + formula1 + " , " + formula2 + " , " + formula3); } //update maximum likelihood maxlike = new_maxlike; @@ -252,9 +252,9 @@ namespace OpenMS String formula2 = ((this)->*(getPositiveGnuplotFormula_))(correctly_assigned_fit_param_) + "* (1 - " + String(negative_prior_) + ")"; // String(correctly_assigned_fit_param_.A) +" * exp(-(x - " + String(correctly_assigned_fit_param_.x0) + ") ** 2 / 2 / (" + String(correctly_assigned_fit_param_.sigma) + ") ** 2)"+ "* (1 - " + String(negative_prior_) + ")"; String formula3 = getBothGnuplotFormula(incorrectly_assigned_fit_param_, correctly_assigned_fit_param_); // important: use single quotes for paths, since otherwise backslashes will not be accepted on Windows! - file.addLine("plot '" + (String)param_.getValue("out_plot") + "_scores.txt' with boxes, " + formula1 + " , " + formula2 + " , " + formula3); - file.store((String)param_.getValue("out_plot")); - tryGnuplot((String)param_.getValue("out_plot")); + file.addLine("plot '" + (std::string)param_.getValue("out_plot") + "_scores.txt' with boxes, " + formula1 + " , " + formula2 + " , " + formula3); + file.store((std::string)param_.getValue("out_plot")); + tryGnuplot((std::string)param_.getValue("out_plot")); } return good_fit; } @@ -304,12 +304,12 @@ namespace OpenMS //------------------------------------------------------------- // create files for output //------------------------------------------------------------- - bool output_plots = (param_.getValue("out_plot").toString().trim().length() > 0); + bool output_plots = (String(param_.getValue("out_plot").toString()).trim().length() > 0); TextFile file; if (output_plots) { // create output directory (if not already present) - QDir dir(param_.getValue("out_plot").toString().toQString()); + QDir dir(String(param_.getValue("out_plot").toString()).toQString()); if (!dir.cdUp()) { OPENMS_LOG_ERROR << "Could not navigate to output directory for plots from '" << String(dir.dirName()) << "'." << std::endl; @@ -409,7 +409,7 @@ namespace OpenMS formula2 = ((this)->*(getPositiveGnuplotFormula_))(correctly_assigned_fit_param_) + "* (1 - " + String(negative_prior_) + ")"; //String(correctly_assigned_fit_param_.A) +" * exp(-(x - " + String(correctly_assigned_fit_param_.x0) + ") ** 2 / 2 / (" + String(correctly_assigned_fit_param_.sigma) + ") ** 2)"+ "* (1 - " + String(negative_prior_) + ")"; formula3 = getBothGnuplotFormula(incorrectly_assigned_fit_param_, correctly_assigned_fit_param_); // important: use single quotes for paths, since otherwise backslashes will not be accepted on Windows! - file.addLine("plot '" + (String)param_.getValue("out_plot") + "_scores.txt' with boxes, " + formula1 + " , " + formula2 + " , " + formula3); + file.addLine("plot '" + (std::string)param_.getValue("out_plot") + "_scores.txt' with boxes, " + formula1 + " , " + formula2 + " , " + formula3); } //update maximum likelihood maxlike = new_maxlike; @@ -435,9 +435,9 @@ namespace OpenMS String formula2 = ((this)->*(getPositiveGnuplotFormula_))(correctly_assigned_fit_param_) + "* (1 - " + String(negative_prior_) + ")"; // String(correctly_assigned_fit_param_.A) +" * exp(-(x - " + String(correctly_assigned_fit_param_.x0) + ") ** 2 / 2 / (" + String(correctly_assigned_fit_param_.sigma) + ") ** 2)"+ "* (1 - " + String(negative_prior_) + ")"; String formula3 = getBothGnuplotFormula(incorrectly_assigned_fit_param_, correctly_assigned_fit_param_); // important: use single quotes for paths, since otherwise backslashes will not be accepted on Windows! - file.addLine("plot '" + (String)param_.getValue("out_plot") + "_scores.txt' with boxes, " + formula1 + " , " + formula2 + " , " + formula3); - file.store((String)param_.getValue("out_plot")); - tryGnuplot((String)param_.getValue("out_plot")); + file.addLine("plot '" + (std::string)param_.getValue("out_plot") + "_scores.txt' with boxes, " + formula1 + " , " + formula2 + " , " + formula3); + file.store((std::string)param_.getValue("out_plot")); + tryGnuplot((std::string)param_.getValue("out_plot")); } return good_fit; } @@ -653,7 +653,7 @@ namespace OpenMS it->setY(it->getY() / (x_scores.size() * dividing_score)); data_points << (String(it->getX()) + "\t" + it->getY()); } - data_points.store((String)param_.getValue("out_plot") + "_scores.txt"); + data_points.store((std::string)param_.getValue("out_plot") + "_scores.txt"); TextFile file; file << "set terminal pdf color solid linewidth 2.0 rounded"; @@ -664,11 +664,11 @@ namespace OpenMS //TODO: file<<"set title "; file << "set key off"; // important: use single quotes for paths, since otherwise backslashes will not be accepted on Windows! - file << "set output '" + (String)param_.getValue("out_plot") + ".pdf'"; + file << "set output '" + (std::string)param_.getValue("out_plot") + ".pdf'"; String formula1 = ((this)->*(getNegativeGnuplotFormula_))(incorrectly_assigned_fit_param_) + "* " + String(negative_prior_); //String(incorrectly_assigned_fit_param_.A) +" * exp(-(x - " + String(incorrectly_assigned_fit_param_.x0) + ") ** 2 / 2 / (" + String(incorrectly_assigned_fit_param_.sigma) + ") ** 2)"+ "*" + String(negative_prior_); String formula2 = ((this)->*(getPositiveGnuplotFormula_))(correctly_assigned_fit_param_) + "* (1 - " + String(negative_prior_) + ")"; //String(correctly_assigned_fit_param_.A) +" * exp(-(x - " + String(correctly_assigned_fit_param_.x0) + ") ** 2 / 2 / (" + String(correctly_assigned_fit_param_.sigma) + ") ** 2)"+ "* (1 - " + String(negative_prior_) + ")"; // important: use single quotes for paths, since otherwise backslashes will not be accepted on Windows! - file << ("plot '" + (String)param_.getValue("out_plot") + "_scores.txt' with boxes, " + formula1 + " , " + formula2); + file << ("plot '" + (std::string)param_.getValue("out_plot") + "_scores.txt' with boxes, " + formula1 + " , " + formula2); return file; } @@ -777,7 +777,7 @@ namespace OpenMS temp_ += (*it)[2]; data_points << temp_; } - data_points.store((String)param_.getValue("out_plot") + "_target_decoy_scores.txt"); + data_points.store((std::string)param_.getValue("out_plot") + "_target_decoy_scores.txt"); TextFile file; file << "set terminal pdf color solid linewidth 2.0 rounded"; //file<<"set style empty solid 0.5 border -1"; @@ -787,14 +787,14 @@ namespace OpenMS //TODO: file<<"set title "; file << "set key off"; // important: use single quotes for paths, since otherwise backslashes will not be accepted on Windows! - file << String("set output '") + (String)param_.getValue("out_plot") + "_target_decoy.pdf'"; + file << "set output '" + (std::string)param_.getValue("out_plot") + "_target_decoy.pdf'"; String formula1, formula2; formula1 = getGumbelGnuplotFormula(getIncorrectlyAssignedFitResult()) + "* " + String(getNegativePrior()); //String(incorrectly_assigned_fit_param_.A) +" * exp(-(x - " + String(incorrectly_assigned_fit_param_.x0) + ") ** 2 / 2 / (" + String(incorrectly_assigned_fit_param_.sigma) + ") ** 2)"+ "*" + String(negative_prior_); formula2 = getGaussGnuplotFormula(getCorrectlyAssignedFitResult()) + "* (1 - " + String(getNegativePrior()) + ")"; //String(correctly_assigned_fit_param_.A) +" * exp(-(x - " + String(correctly_assigned_fit_param_.x0) + ") ** 2 / 2 / (" + String(correctly_assigned_fit_param_.sigma) + ") ** 2)"+ "* (1 - " + String(negative_prior_) + ")"; // important: use single quotes for paths, since otherwise backslashes will not be accepted on Windows! - file << ("plot '" + (String)param_.getValue("out_plot") + "_target_decoy_scores.txt' using 1:3 with boxes fill solid 0.8 noborder, \"" + (String)param_.getValue("out_plot") + "_target_decoy_scores.txt\" using 1:2 with boxes, " + formula1 + " , " + formula2); - file.store((String)param_.getValue("out_plot") + "_target_decoy"); - tryGnuplot((String)param_.getValue("out_plot") + "_target_decoy"); + file << ("plot '" + (std::string)param_.getValue("out_plot") + "_target_decoy_scores.txt' using 1:3 with boxes fill solid 0.8 noborder, \"" + (std::string)param_.getValue("out_plot") + "_target_decoy_scores.txt\" using 1:2 with boxes, " + formula1 + " , " + formula2); + file.store((std::string)param_.getValue("out_plot") + "_target_decoy"); + tryGnuplot((std::string)param_.getValue("out_plot") + "_target_decoy"); } void PosteriorErrorProbabilityModel::tryGnuplot(const String& gp_file) @@ -873,7 +873,7 @@ namespace OpenMS } } - double PosteriorErrorProbabilityModel::getScore_(const StringList& requested_score_types, const PeptideHit & hit, const String& actual_score_type) + double PosteriorErrorProbabilityModel::getScore_(const std::vector& requested_score_types, const PeptideHit & hit, const String& actual_score_type) { for (const auto& requested_score_type : requested_score_types) { diff --git a/src/openms/source/METADATA/SpectrumLookup.cpp b/src/openms/source/METADATA/SpectrumLookup.cpp index 338987e1cd8..6dbb323b2d4 100644 --- a/src/openms/source/METADATA/SpectrumLookup.cpp +++ b/src/openms/source/METADATA/SpectrumLookup.cpp @@ -38,7 +38,7 @@ using namespace std; namespace OpenMS { - const String& SpectrumLookup::default_scan_regexp = "=(?\\d+)$"; + const String& SpectrumLookup::default_scan_regexp = R"(=(?\d+)$)"; const String& SpectrumLookup::regexp_names_ = "INDEX0 INDEX1 SCAN ID RT"; @@ -267,38 +267,38 @@ namespace OpenMS // "scan=NUMBER" if (std::find(scan.begin(), scan.end(), native_id_type_accession) != scan.end()) { - regexp = std::string("scan=(?\\d+)"); + regexp = std::string(R"(scan=(?\d+))"); } // id="sample=1 period=1 cycle=96 experiment=1" - this will be described by a combination of (cycle * 1000 + experiment) else if (native_id_type_accession == "MS:1000770") // WIFF nativeID format { - regexp = std::string("cycle=(?\\d+).experiment=(?\\d+)"); + regexp = std::string(R"(cycle=(?\d+).experiment=(?\d+))"); subgroups = {1, 2}; } // "file=NUMBER" else if (std::find(file.begin(), file.end(), native_id_type_accession) != file.end()) { - regexp = std::string("file=(?\\d+)"); + regexp = std::string(R"(file=(?\d+))"); } // "index=NUMBER" else if (native_id_type_accession == "MS:1000774") { - regexp = std::string("index=(?\\d+)"); + regexp = std::string(R"(index=(?\d+))"); } // "scanId=NUMBER" - MS_Agilent_MassHunter_nativeID_format else if (native_id_type_accession == "MS:1001508") { - regexp = std::string("scanId=(?\\d+)"); + regexp = std::string(R"(scanId=(?\d+))"); } // "spectrum=NUMBER" else if (native_id_type_accession == "MS:1000777") { - regexp = std::string("spectrum=(?\\d+)"); + regexp = std::string(R"(spectrum=(?\d+))"); } // NUMBER else if (native_id_type_accession == "MS:1001530") { - regexp = std::string("(?\\d+)"); + regexp = std::string(R"((?\d+))"); } else { diff --git a/src/openms/source/QC/SpectrumCount.cpp b/src/openms/source/QC/SpectrumCount.cpp new file mode 100644 index 00000000000..de6c6c5c1a2 --- /dev/null +++ b/src/openms/source/QC/SpectrumCount.cpp @@ -0,0 +1,66 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARSpectrumCountULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: Axel Walter $ +// $Authors: Axel Walter $ +// -------------------------------------------------------------------------- + + +#include +#include +using namespace std; + +namespace OpenMS +{ + + map SpectrumCount::compute(const MSExperiment& exp) + { + map counts; + for (const auto& spectrum : exp) + { + const Size level = spectrum.getMSLevel(); + ++counts[level]; // count MS level + } + return counts; + } + + /// Returns the name of the metric + const String& SpectrumCount::getName() const + { + return name_; + } + + /// Returns required file input i.e. MzML. + /// This is encoded as a bit in a Status object. + QCBase::Status SpectrumCount::requires() const + { + return QCBase::Status(QCBase::Requires::RAWMZML); + } +} diff --git a/src/openms/source/QC/TIC.cpp b/src/openms/source/QC/TIC.cpp index 97908ec0ced..f31d4a2d32a 100644 --- a/src/openms/source/QC/TIC.cpp +++ b/src/openms/source/QC/TIC.cpp @@ -40,15 +40,45 @@ using namespace std; namespace OpenMS -{ - /// Reset - void TIC::clear() +{ + + TIC::Result TIC::compute(const MSExperiment& exp, float bin_size) { - results_.clear(); + TIC::Result result; + MSChromatogram tic = exp.getTIC(bin_size); + if (!tic.empty()) + { + for (const auto& p : tic) + { + result.intensities.push_back(p.getIntensity()); + result.retention_times.push_back(p.getRT()); + } + + result.area = result.intensities[0]; + + for (size_t i = 1; i < result.intensities.size(); ++i) + { + result.area += result.intensities[i]; + if (result.intensities[i] > result.intensities[i-1] * 10) // detect 10x jumps between two subsequent scans + { + ++result.jump; + } + if (result.intensities[i] < result.intensities[i-1] / 10) // detect 10x falls between two subsequent scans + { + ++result.fall; + } + } + } + return result; } - void TIC::compute(const MSExperiment &exp, float bin_size) + + bool TIC::Result::operator==(const Result& rhs) const { - results_.push_back(exp.getTIC(bin_size)); + return intensities == rhs.intensities + && retention_times == rhs.retention_times + && area == rhs.area + && fall == rhs.fall + && jump == rhs.jump; } /// Returns the name of the metric @@ -56,12 +86,6 @@ namespace OpenMS { return name_; } - - /// Returns all results calculated with compute. - const std::vector& TIC::getResults() const - { - return results_; - } /// Returns required file input i.e. MzML. /// This is encoded as a bit in a Status object. @@ -70,23 +94,21 @@ namespace OpenMS return QCBase::Status(QCBase::Requires::RAWMZML); } - void TIC::addMetaDataMetricsToMzTab(OpenMS::MzTabMetaData& meta) + void TIC::addMetaDataMetricsToMzTab(OpenMS::MzTabMetaData& meta, vector& tics) { // Adding TIC information to meta data - const auto& tics = this->getResults(); for (Size i = 0; i < tics.size(); ++i) { - if (tics[i].empty()) continue; // no MS1 spectra - + if (tics[i].intensities.empty()) continue; // no MS1 spectra MzTabParameter tic{}; tic.setCVLabel("total ion current"); tic.setAccession("MS:1000285"); tic.setName("TIC_" + String(i + 1)); String value("["); - value += String(tics[i][0].getRT(), false) + ", " + String((UInt64)tics[i][0].getIntensity()); - for (Size j = 1; j < tics[i].size(); ++j) + value += String(tics[i].retention_times[0], false) + ", " + String((UInt64)tics[i].intensities[0]); + for (Size j = 1; j < tics[i].intensities.size(); ++j) { - value += ", " + String(tics[i][j].getRT(), false) + ", " + String((UInt64)tics[i][j].getIntensity()); + value += ", " + String(tics[i].retention_times[j], false) + ", " + String((UInt64)tics[i].intensities[j]); } value += "]"; tic.setValue(value); diff --git a/src/openms/source/QC/sources.cmake b/src/openms/source/QC/sources.cmake index 315a1a3ad97..a0131e47e84 100644 --- a/src/openms/source/QC/sources.cmake +++ b/src/openms/source/QC/sources.cmake @@ -14,6 +14,7 @@ set(sources_list PSMExplainedIonCurrent.cpp QCBase.cpp RTAlignment.cpp + SpectrumCount.cpp DBSuitability.cpp TIC.cpp ) diff --git a/src/openms/source/SIMULATION/DetectabilitySimulation.cpp b/src/openms/source/SIMULATION/DetectabilitySimulation.cpp index 384bd67b77d..dcc9d2eb538 100644 --- a/src/openms/source/SIMULATION/DetectabilitySimulation.cpp +++ b/src/openms/source/SIMULATION/DetectabilitySimulation.cpp @@ -129,26 +129,26 @@ namespace OpenMS ParamXMLFile paramFile; paramFile.load(add_paramfile, additional_parameters); - if (additional_parameters.getValue("border_length") == DataValue::EMPTY + if (additional_parameters.getValue("border_length") == ParamValue::EMPTY && svm.getIntParameter(SVMWrapper::KERNEL_TYPE) == SVMWrapper::OLIGO) { throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "DetectibilitySimulation: No border length defined in additional parameters file."); } - border_length = ((String)additional_parameters.getValue("border_length")).toInt(); - if (additional_parameters.getValue("k_mer_length") == DataValue::EMPTY + border_length = ((String)additional_parameters.getValue("border_length").toString()).toInt(); + if (additional_parameters.getValue("k_mer_length") == ParamValue::EMPTY && svm.getIntParameter(SVMWrapper::KERNEL_TYPE) == SVMWrapper::OLIGO) { throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "DetectibilitySimulation: No k-mer length defined in additional parameters file."); } - k_mer_length = ((String)additional_parameters.getValue("k_mer_length")).toInt(); + k_mer_length = ((String)additional_parameters.getValue("k_mer_length").toString()).toInt(); - if (additional_parameters.getValue("sigma") == DataValue::EMPTY + if (additional_parameters.getValue("sigma") == ParamValue::EMPTY && svm.getIntParameter(SVMWrapper::KERNEL_TYPE) == SVMWrapper::OLIGO) { throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "DetectibilitySimulation: No sigma defined in additional parameters file."); } - sigma = ((String)additional_parameters.getValue("sigma")).toFloat(); + sigma = ((String)additional_parameters.getValue("sigma").toString()).toFloat(); } if (File::readable(dt_model_file_)) @@ -230,7 +230,7 @@ namespace OpenMS void DetectabilitySimulation::setDefaultParams_() { defaults_.setValue("dt_simulation_on", "false", "Modelling detectibility enabled? This can serve as a filter to remove peptides which ionize badly, thus reducing peptide count"); - defaults_.setValidStrings("dt_simulation_on", ListUtils::create("true,false")); + defaults_.setValidStrings("dt_simulation_on", {"true","false"}); defaults_.setValue("min_detect", 0.5, "Minimum peptide detectability accepted. Peptides with a lower score will be removed"); defaults_.setValue("dt_model_file", "examples/simulation/DTPredict.model", "SVM model for peptide detectability prediction"); defaultsToParam_(); @@ -239,7 +239,7 @@ namespace OpenMS void DetectabilitySimulation::updateMembers_() { min_detect_ = param_.getValue("min_detect"); - dt_model_file_ = param_.getValue("dt_model_file"); + dt_model_file_ = param_.getValue("dt_model_file").toString(); if (!File::readable(dt_model_file_)) // look in OPENMS_DATA_PATH { dt_model_file_ = File::find(dt_model_file_); diff --git a/src/openms/source/SIMULATION/DigestSimulation.cpp b/src/openms/source/SIMULATION/DigestSimulation.cpp index 5f0f96b89a6..782034b7b5d 100644 --- a/src/openms/source/SIMULATION/DigestSimulation.cpp +++ b/src/openms/source/SIMULATION/DigestSimulation.cpp @@ -71,11 +71,11 @@ namespace OpenMS StringList enzymes; ProteaseDB::getInstance()->getAllNames(enzymes); defaults_.setValue("enzyme", "Trypsin", "Enzyme to use for digestion (select 'no cleavage' to skip digestion)"); - defaults_.setValidStrings("enzyme", enzymes); + defaults_.setValidStrings("enzyme", ListUtils::create(enzymes)); // cleavages defaults_.setValue("model", "naive", "The cleavage model to use for digestion. 'Trained' is based on a log likelihood model (see DOI:10.1021/pr060507u)."); - defaults_.setValidStrings("model", ListUtils::create("trained,naive")); + defaults_.setValidStrings("model", {"trained","naive"}); defaults_.setValue("model_trained:threshold", 0.50, "Model threshold for calling a cleavage. Higher values increase the number of cleavages. -2 will give no cleavages, +4 almost full cleavage."); defaults_.setMinFloat("model_trained:threshold", -2); @@ -95,7 +95,7 @@ namespace OpenMS { OPENMS_LOG_INFO << "Digest Simulation ... started" << std::endl; - if ((String)param_.getValue("enzyme") == String("no cleavage")) + if (param_.getValue("enzyme") == "no cleavage") { //peptides = proteins; // convert all proteins into peptides @@ -148,7 +148,7 @@ namespace OpenMS else { ProteaseDigestion digestion; - digestion.setEnzyme((String)param_.getValue("enzyme")); + digestion.setEnzyme((String)param_.getValue("enzyme").toString()); } std::vector digestion_products; @@ -176,7 +176,7 @@ namespace OpenMS else { ProteaseDigestion digestion; - digestion.setEnzyme((String)param_.getValue("enzyme")); + digestion.setEnzyme((String)param_.getValue("enzyme").toString()); digestion.setMissedCleavages(0); complete_digest_count = digestion.peptideCount(AASequence::fromString(protein_hit->getSequence())); } @@ -216,7 +216,7 @@ namespace OpenMS else { ProteaseDigestion digestion; - digestion.setEnzyme((String)param_.getValue("enzyme")); + digestion.setEnzyme((String)param_.getValue("enzyme").toString()); digestion.setMissedCleavages(missed_cleavages); digestion.digest(AASequence::fromString(protein_hit->getSequence()), digestion_products); } diff --git a/src/openms/source/SIMULATION/EGHFitter1D.cpp b/src/openms/source/SIMULATION/EGHFitter1D.cpp index de42a0c0047..86877327f2d 100644 --- a/src/openms/source/SIMULATION/EGHFitter1D.cpp +++ b/src/openms/source/SIMULATION/EGHFitter1D.cpp @@ -142,7 +142,7 @@ namespace OpenMS LevMarqFitter1D() { setName(getProductName()); - defaults_.setValue("statistics:variance", 1.0, "Variance of the model.", ListUtils::create("advanced")); + defaults_.setValue("statistics:variance", 1.0, "Variance of the model.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/SIMULATION/EGHModel.cpp b/src/openms/source/SIMULATION/EGHModel.cpp index b92bd3adb51..c70b047f677 100644 --- a/src/openms/source/SIMULATION/EGHModel.cpp +++ b/src/openms/source/SIMULATION/EGHModel.cpp @@ -49,16 +49,16 @@ namespace OpenMS // Since the interpolation table is (re-)initialized after setting // parameters, we set an empty bounding_box to avoid silly computations. - defaults_.setValue("interpolation_step", 0.1, "Sampling rate for the interpolation of the model function.", ListUtils::create("advanced")); + defaults_.setValue("interpolation_step", 0.1, "Sampling rate for the interpolation of the model function.", {"advanced"}); - defaults_.setValue("statistics:mean", 0.0f, "Centroid position of the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:variance", 1.0f, "The variance of the model.", ListUtils::create("advanced")); + defaults_.setValue("statistics:mean", 0.0f, "Centroid position of the model.", {"advanced"}); + defaults_.setValue("statistics:variance", 1.0f, "The variance of the model.", {"advanced"}); defaults_.setValue("egh:height", 1000.0f, "Height of the exponential-Gaussian hybrid."); - defaults_.setValue("egh:retention", 1200.0f, "Retention time of the exponential-Gaussian hybrid.", ListUtils::create("advanced")); + defaults_.setValue("egh:retention", 1200.0f, "Retention time of the exponential-Gaussian hybrid.", {"advanced"}); defaults_.setValue("egh:guess_parameter", "true", "If set to true, the EGHModel will try to estimate the model parameters (tau and sigma-square) based on A,B, and alpha. If set to false, it will use the parameters tau and sigma-square directly."); - defaults_.setValidStrings("egh:guess_parameter", ListUtils::create("true,false")); + defaults_.setValidStrings("egh:guess_parameter", {"true","false"}); defaults_.setValue("egh:A", 100.0f, "Horizontal distance between the vertical line at the peak maximum (H) and the leading line where the EGH has H*alpha (e.g. the left half-max for alpha=0.5)."); defaults_.setValue("egh:B", 100.0f, "Horizontal distance between the vertical line at the peak maximum (H) and the trailing line where the EGH has H*alpha (e.g. the right half-max for alpha=0.5)."); @@ -67,15 +67,15 @@ namespace OpenMS defaults_.setMaxFloat("egh:alpha", 1.0); - defaults_.setValue("egh:tau", 0.0, "Time constant of the exponential decay (tau is zero for gaussian peaks).", ListUtils::create("advanced")); - defaults_.setValue("egh:sigma_square", 1803.4, "Standard deviation of the peak.", ListUtils::create("advanced")); + defaults_.setValue("egh:tau", 0.0, "Time constant of the exponential decay (tau is zero for gaussian peaks).", {"advanced"}); + defaults_.setValue("egh:sigma_square", 1803.4, "Standard deviation of the peak.", {"advanced"}); defaults_.setMinFloat("egh:sigma_square", 0.0); defaults_.setValue("bounding_box:compute", "true", "If true, the EGHModel will compute its own bounding box."); - defaults_.setValidStrings("bounding_box:compute", ListUtils::create("true,false")); + defaults_.setValidStrings("bounding_box:compute", {"true","false"}); - defaults_.setValue("bounding_box:min", 0.0, "Lower end of bounding box enclosing the data used to fit the model.", ListUtils::create("advanced")); - defaults_.setValue("bounding_box:max", 0.0, "Upper end of bounding box enclosing the data used to fit the model.", ListUtils::create("advanced")); + defaults_.setValue("bounding_box:min", 0.0, "Lower end of bounding box enclosing the data used to fit the model.", {"advanced"}); + defaults_.setValue("bounding_box:max", 0.0, "Upper end of bounding box enclosing the data used to fit the model.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/SIMULATION/IonizationSimulation.cpp b/src/openms/source/SIMULATION/IonizationSimulation.cpp index ffbd57ebb77..814bb132f45 100644 --- a/src/openms/source/SIMULATION/IonizationSimulation.cpp +++ b/src/openms/source/SIMULATION/IonizationSimulation.cpp @@ -152,14 +152,14 @@ namespace OpenMS void IonizationSimulation::setDefaultParams_() { defaults_.setValue("ionization_type", "ESI", "Type of Ionization (MALDI or ESI)"); - defaults_.setValidStrings("ionization_type", ListUtils::create("MALDI,ESI")); + defaults_.setValidStrings("ionization_type", {"MALDI","ESI"}); - defaults_.setValue("esi:ionized_residues", ListUtils::create("Arg,Lys,His"), "List of residues (as three letter code) that will be considered during ES ionization. The N-term is always assumed to carry a charge. This parameter will be ignored during MALDI ionization"); - StringList valid_ionized_residues = ListUtils::create("Ala,Cys,Asp,Glu,Phe,Gly,His,Ile,Lys,Leu,Met,Asn,Pro,Gln,Arg,Sec,Ser,Thr,Val,Trp,Tyr"); + defaults_.setValue("esi:ionized_residues", std::vector{"Arg","Lys","His"}, "List of residues (as three letter code) that will be considered during ES ionization. The N-term is always assumed to carry a charge. This parameter will be ignored during MALDI ionization"); + std::vector valid_ionized_residues = {"Ala","Cys","Asp","Glu","Phe","Gly","His","Ile","Lys","Leu","Met","Asn","Pro","Gln","Arg","Sec","Ser","Thr","Val","Trp","Tyr"}; defaults_.setValidStrings("esi:ionized_residues", valid_ionized_residues); - defaults_.setValue("esi:charge_impurity", ListUtils::create("H+:1"), "List of charged ions that contribute to charge with weight of occurrence (their sum is scaled to 1 internally), e.g. ['H:1'] or ['H:0.7' 'Na:0.3'], ['H:4' 'Na:1'] (which internally translates to ['H:0.8' 'Na:0.2'])"); + defaults_.setValue("esi:charge_impurity", std::vector{"H+:1"}, "List of charged ions that contribute to charge with weight of occurrence (their sum is scaled to 1 internally), e.g. ['H:1'] or ['H:0.7' 'Na:0.3'], ['H:4' 'Na:1'] (which internally translates to ['H:0.8' 'Na:0.2'])"); - defaults_.setValue("esi:max_impurity_set_size", 3, "Maximal #combinations of charge impurities allowed (each generating one feature) per charge state. E.g. assuming charge=3 and this parameter is 2, then we could choose to allow '3H+, 2H+Na+' features (given a certain 'charge_impurity' constraints), but no '3H+, 2H+Na+, 3Na+'", ListUtils::create("advanced")); + defaults_.setValue("esi:max_impurity_set_size", 3, "Maximal #combinations of charge impurities allowed (each generating one feature) per charge state. E.g. assuming charge=3 and this parameter is 2, then we could choose to allow '3H+, 2H+Na+' features (given a certain 'charge_impurity' constraints), but no '3H+, 2H+Na+, 3Na+'", {"advanced"}); // ionization probabilities defaults_.setValue("esi:ionization_probability", 0.8, "Probability for the binomial distribution of the ESI charge states"); @@ -176,7 +176,7 @@ namespace OpenMS void IonizationSimulation::updateMembers_() { - String type = param_.getValue("ionization_type"); + const std::string& type = param_.getValue("ionization_type"); if (type == "ESI") { ionization_type_ = ESI; @@ -193,14 +193,14 @@ namespace OpenMS // get basic residues from params basic_residues_.clear(); - StringList basic_residues = param_.getValue("esi:ionized_residues"); - for (StringList::const_iterator it = basic_residues.begin(); it != basic_residues.end(); ++it) + const std::vector& basic_residues = param_.getValue("esi:ionized_residues"); + for (std::vector::const_iterator it = basic_residues.begin(); it != basic_residues.end(); ++it) { basic_residues_.insert(*it); } // parse possible ESI adducts - StringList esi_charge_impurity = param_.getValue("esi:charge_impurity"); + StringList esi_charge_impurity = ListUtils::toStringList(param_.getValue("esi:charge_impurity")); if (esi_charge_impurity.empty()) throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, String("IonizationSimulation got empty esi:charge_impurity! You need to specify at least one adduct (usually 'H+:1')")); StringList components; diff --git a/src/openms/source/SIMULATION/LABELING/ICPLLabeler.cpp b/src/openms/source/SIMULATION/LABELING/ICPLLabeler.cpp index 26429b80d54..5035a821ec3 100644 --- a/src/openms/source/SIMULATION/LABELING/ICPLLabeler.cpp +++ b/src/openms/source/SIMULATION/LABELING/ICPLLabeler.cpp @@ -53,12 +53,12 @@ namespace OpenMS defaults_.setValue("ICPL_fixed_rtshift", 0.0, "Fixed retention time shift between labeled pairs. If set to 0.0 only the retention times, computed by the RT model step are used."); //defaults for protein-labeling defaults_.setValue("label_proteins", "true", "Enables protein-labeling. (select 'false' if you only need peptide-labeling)"); - defaults_.setValidStrings("label_proteins", ListUtils::create("true,false")); + defaults_.setValidStrings("label_proteins", {"true","false"}); // labels - defaults_.setValue("ICPL_light_channel_label", "UniMod:365", "UniMod Id of the light channel ICPL label.", ListUtils::create("advanced")); - defaults_.setValue("ICPL_medium_channel_label", "UniMod:687", "UniMod Id of the medium channel ICPL label.", ListUtils::create("advanced")); - defaults_.setValue("ICPL_heavy_channel_label", "UniMod:364", "UniMod Id of the heavy channel ICPL label.", ListUtils::create("advanced")); + defaults_.setValue("ICPL_light_channel_label", "UniMod:365", "UniMod Id of the light channel ICPL label.", {"advanced"}); + defaults_.setValue("ICPL_medium_channel_label", "UniMod:687", "UniMod Id of the medium channel ICPL label.", {"advanced"}); + defaults_.setValue("ICPL_heavy_channel_label", "UniMod:364", "UniMod Id of the heavy channel ICPL label.", {"advanced"}); defaultsToParam_(); } @@ -508,9 +508,9 @@ namespace OpenMS void ICPLLabeler::updateMembers_() { - light_channel_label_ = param_.getValue("ICPL_light_channel_label"); - medium_channel_label_ = param_.getValue("ICPL_medium_channel_label"); - heavy_channel_label_ = param_.getValue("ICPL_heavy_channel_label"); + light_channel_label_ = param_.getValue("ICPL_light_channel_label").toString(); + medium_channel_label_ = param_.getValue("ICPL_medium_channel_label").toString(); + heavy_channel_label_ = param_.getValue("ICPL_heavy_channel_label").toString(); } String ICPLLabeler::getUnmodifiedAASequence_(const Feature& feature, const String& label) const diff --git a/src/openms/source/SIMULATION/LABELING/ITRAQLabeler.cpp b/src/openms/source/SIMULATION/LABELING/ITRAQLabeler.cpp index 8d4f979384f..c9b044502ef 100644 --- a/src/openms/source/SIMULATION/LABELING/ITRAQLabeler.cpp +++ b/src/openms/source/SIMULATION/LABELING/ITRAQLabeler.cpp @@ -63,19 +63,19 @@ namespace OpenMS // iTRAQ defaults_.setValue("iTRAQ", "4plex", "4plex or 8plex iTRAQ?"); - defaults_.setValidStrings("iTRAQ", ListUtils::create("4plex,8plex")); + defaults_.setValidStrings("iTRAQ", {"4plex","8plex"}); defaults_.setValue("reporter_mass_shift", 0.1, "Allowed shift (uniformly distributed - left to right) in Da from the expected position (of e.g. 114.1, 115.1)"); defaults_.setMinFloat("reporter_mass_shift", 0); defaults_.setMaxFloat("reporter_mass_shift", 0.5); - defaults_.setValue("channel_active_4plex", ListUtils::create("114:myReference"), "Four-plex only: Each channel that was used in the experiment and its description (114-117) in format :, e.g. \"114:myref\",\"115:liver\"."); - defaults_.setValue("channel_active_8plex", ListUtils::create("113:myReference"), "Eight-plex only: Each channel that was used in the experiment and its description (113-121) in format :, e.g. \"113:myref\",\"115:liver\",\"118:lung\"."); + defaults_.setValue("channel_active_4plex", std::vector{"114:myReference"}, "Four-plex only: Each channel that was used in the experiment and its description (114-117) in format :, e.g. \"114:myref\",\"115:liver\"."); + defaults_.setValue("channel_active_8plex", std::vector{"113:myReference"}, "Eight-plex only: Each channel that was used in the experiment and its description (113-121) in format :, e.g. \"113:myref\",\"115:liver\",\"118:lung\"."); StringList isotopes = ItraqConstants::getIsotopeMatrixAsStringList(ItraqConstants::FOURPLEX, isotope_corrections_); - defaults_.setValue("isotope_correction_values_4plex", isotopes, "override default values (see Documentation); use the following format: :<-2Da>/<-1Da>/<+1Da>/<+2Da> ; e.g. '114:0/0.3/4/0' , '116:0.1/0.3/3/0.2' ", ListUtils::create("advanced")); + defaults_.setValue("isotope_correction_values_4plex", ListUtils::create(isotopes), "override default values (see Documentation); use the following format: :<-2Da>/<-1Da>/<+1Da>/<+2Da> ; e.g. '114:0/0.3/4/0' , '116:0.1/0.3/3/0.2' ", {"advanced"}); isotopes = ItraqConstants::getIsotopeMatrixAsStringList(ItraqConstants::EIGHTPLEX, isotope_corrections_); - defaults_.setValue("isotope_correction_values_8plex", isotopes, "override default values (see Documentation); use the following format: :<-2Da>/<-1Da>/<+1Da>/<+2Da> ; e.g. '113:0/0.3/4/0' , '116:0.1/0.3/3/0.2' ", ListUtils::create("advanced")); + defaults_.setValue("isotope_correction_values_8plex", ListUtils::create(isotopes), "override default values (see Documentation); use the following format: :<-2Da>/<-1Da>/<+1Da>/<+2Da> ; e.g. '113:0/0.3/4/0' , '116:0.1/0.3/3/0.2' ", {"advanced"}); defaults_.setValue("Y_contamination", 0.3, "Efficiency of labeling tyrosine ('Y') residues. 0=off, 1=full labeling"); defaults_.setMinFloat("Y_contamination", 0.0); @@ -95,12 +95,12 @@ namespace OpenMS if (param_.getValue("iTRAQ") == "4plex") { itraq_type_ = ItraqConstants::FOURPLEX; - channels_active = param_.getValue("channel_active_4plex"); + channels_active = ListUtils::toStringList(param_.getValue("channel_active_4plex")); } else if (param_.getValue("iTRAQ") == "8plex") { itraq_type_ = ItraqConstants::EIGHTPLEX; - channels_active = param_.getValue("channel_active_8plex"); + channels_active = ListUtils::toStringList(param_.getValue("channel_active_8plex")); } ItraqConstants::initChannelMap(itraq_type_, channel_map_); @@ -111,11 +111,11 @@ namespace OpenMS StringList channels; if (itraq_type_ == ItraqConstants::FOURPLEX) { - channels = param_.getValue("isotope_correction_values_4plex"); + channels = ListUtils::toStringList(param_.getValue("isotope_correction_values_4plex")); } else { - channels = param_.getValue("isotope_correction_values_8plex"); + channels = ListUtils::toStringList(param_.getValue("isotope_correction_values_8plex")); } if (channels.size() > 0) { diff --git a/src/openms/source/SIMULATION/LABELING/SILACLabeler.cpp b/src/openms/source/SIMULATION/LABELING/SILACLabeler.cpp index 9836d2cc3af..4073851ecf1 100644 --- a/src/openms/source/SIMULATION/LABELING/SILACLabeler.cpp +++ b/src/openms/source/SIMULATION/LABELING/SILACLabeler.cpp @@ -66,11 +66,11 @@ namespace OpenMS void SILACLabeler::updateMembers_() { - medium_channel_lysine_label_ = (String)param_.getValue("medium_channel:modification_lysine"); - medium_channel_arginine_label_ = (String)param_.getValue("medium_channel:modification_arginine"); + medium_channel_lysine_label_ = (String)param_.getValue("medium_channel:modification_lysine").toString(); + medium_channel_arginine_label_ = (String)param_.getValue("medium_channel:modification_arginine").toString(); - heavy_channel_lysine_label_ = (String)param_.getValue("heavy_channel:modification_lysine"); - heavy_channel_arginine_label_ = (String)param_.getValue("heavy_channel:modification_arginine"); + heavy_channel_lysine_label_ = (String)param_.getValue("heavy_channel:modification_lysine").toString(); + heavy_channel_arginine_label_ = (String)param_.getValue("heavy_channel:modification_arginine").toString(); } bool SILACLabeler::canModificationBeApplied_(const String& modification_id, const String& aa) const diff --git a/src/openms/source/SIMULATION/MSSim.cpp b/src/openms/source/SIMULATION/MSSim.cpp index b5aafae53af..dfa89318ef8 100644 --- a/src/openms/source/SIMULATION/MSSim.cpp +++ b/src/openms/source/SIMULATION/MSSim.cpp @@ -135,9 +135,8 @@ namespace OpenMS tmp.insert("", this->param_); // get non-labeling options vector products = Factory::registeredProducts(); - tmp.setValue("Labeling:type", "labelfree", "Select the labeling type you want for your experiment"); - tmp.setValidStrings("Labeling:type", products); + tmp.setValidStrings("Labeling:type", ListUtils::create(products)); for (vector::iterator product_name = products.begin(); product_name != products.end(); ++product_name) { @@ -204,7 +203,7 @@ namespace OpenMS raw_sim.loadContaminants(); // check if the file is valid (if not, an error is raised here instead of half-way through simulation) - String labeling = param_.getValue("Labeling:type"); + String labeling = param_.getValue("Labeling:type").toString(); labeler_ = Factory::create(labeling); Param labeling_parameters = param_.copy("Labeling:" + labeling + ":", true); labeler_->setParameters(labeling_parameters); diff --git a/src/openms/source/SIMULATION/RTSimulation.cpp b/src/openms/source/SIMULATION/RTSimulation.cpp index 4b68ae68828..a3ff5e4cdf0 100644 --- a/src/openms/source/SIMULATION/RTSimulation.cpp +++ b/src/openms/source/SIMULATION/RTSimulation.cpp @@ -87,11 +87,11 @@ namespace OpenMS void RTSimulation::setDefaultParams_() { defaults_.setValue("rt_column", "HPLC", "Modelling of an RT or CE column"); - defaults_.setValidStrings("rt_column", ListUtils::create("none,HPLC,CE")); + defaults_.setValidStrings("rt_column", {"none","HPLC","CE"}); // scaling defaults_.setValue("auto_scale", "true", "Scale predicted RT's/MT's to given 'total_gradient_time'? If 'true', for CE this means that 'CE:lenght_d', 'CE:length_total', 'CE:voltage' have no influence."); - defaults_.setValidStrings("auto_scale", ListUtils::create("true,false")); + defaults_.setValidStrings("auto_scale", {"true","false"}); // column settings defaults_.setValue("total_gradient_time", 2500.0, "The duration [s] of the gradient."); @@ -162,7 +162,7 @@ namespace OpenMS void RTSimulation::updateMembers_() { - rt_model_file_ = param_.getValue("HPLC:model_file"); + rt_model_file_ = param_.getValue("HPLC:model_file").toString(); if (!File::readable(rt_model_file_)) // look in OPENMS_DATA_PATH { rt_model_file_ = File::find(rt_model_file_); @@ -513,26 +513,26 @@ namespace OpenMS ParamXMLFile paramFile; paramFile.load(add_paramfile, additional_parameters); - if (additional_parameters.getValue("border_length") == DataValue::EMPTY + if (additional_parameters.getValue("border_length") == ParamValue::EMPTY && svm.getIntParameter(SVMWrapper::KERNEL_TYPE) == SVMWrapper::OLIGO) { throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "RTSimulation: No border length defined in additional parameters file."); } - border_length = ((String)additional_parameters.getValue("border_length")).toInt(); - if (additional_parameters.getValue("k_mer_length") == DataValue::EMPTY + border_length = ((String)additional_parameters.getValue("border_length").toString()).toInt(); + if (additional_parameters.getValue("k_mer_length") == ParamValue::EMPTY && svm.getIntParameter(SVMWrapper::KERNEL_TYPE) == SVMWrapper::OLIGO) { throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "RTSimulation: No k-mer length defined in additional parameters file."); } - k_mer_length = ((String)additional_parameters.getValue("k_mer_length")).toInt(); + k_mer_length = ((String)additional_parameters.getValue("k_mer_length").toString()).toInt(); - if (additional_parameters.getValue("sigma") == DataValue::EMPTY + if (additional_parameters.getValue("sigma") == ParamValue::EMPTY && svm.getIntParameter(SVMWrapper::KERNEL_TYPE) == SVMWrapper::OLIGO) { throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "RTSimulation: No sigma defined in additional parameters file."); } - sigma = ((String)additional_parameters.getValue("sigma")).toFloat(); + sigma = ((String)additional_parameters.getValue("sigma").toString()).toFloat(); } svm.setParameter(SVMWrapper::BORDER_LENGTH, (Int) border_length); diff --git a/src/openms/source/SIMULATION/RawMSSignalSimulation.cpp b/src/openms/source/SIMULATION/RawMSSignalSimulation.cpp index 07bdfc6d6f0..55cd41ee95e 100644 --- a/src/openms/source/SIMULATION/RawMSSignalSimulation.cpp +++ b/src/openms/source/SIMULATION/RawMSSignalSimulation.cpp @@ -136,18 +136,18 @@ namespace OpenMS void RawMSSignalSimulation::setDefaultParams_() { defaults_.setValue("enabled", "true", "Enable RAW signal simulation? (select 'false' if you only need feature-maps)"); - defaults_.setValidStrings("enabled", ListUtils::create("true,false")); + defaults_.setValidStrings("enabled", {"true","false"}); defaults_.setValue("ionization_type", "ESI", "Type of Ionization (MALDI or ESI)"); - defaults_.setValidStrings("ionization_type", ListUtils::create("MALDI,ESI")); + defaults_.setValidStrings("ionization_type", {"MALDI","ESI"}); // peak and instrument parameter defaults_.setValue("resolution:value", 50000, "Instrument resolution at 400 Th"); defaults_.setValue("resolution:type", "linear", "How does resolution change with increasing m/z?! QTOFs usually show 'constant' behavior, FTs have linear degradation, and on Orbitraps the resolution decreases with square root of mass"); - defaults_.setValidStrings("resolution:type", ListUtils::create("constant,linear,sqrt")); + defaults_.setValidStrings("resolution:type", {"constant","linear","sqrt"}); defaults_.setValue("peak_shape", "Gaussian", "Peak Shape used around each isotope peak (be aware that the area under the curve is constant for both types, but the maximal height will differ (~ 2:3 = Lorentz:Gaussian) due to the wider base of the Lorentzian"); - defaults_.setValidStrings("peak_shape", ListUtils::create("Gaussian,Lorentzian")); + defaults_.setValidStrings("peak_shape", {"Gaussian","Lorentzian"}); // baseline @@ -228,7 +228,7 @@ namespace OpenMS void RawMSSignalSimulation::updateMembers_() { res_base_ = (double) param_.getValue("resolution:value"); - String model = param_.getValue("resolution:type"); + std::string model = param_.getValue("resolution:type"); if (model == "constant") res_model_ = RES_CONSTANT; else if (model == "linear") @@ -252,7 +252,7 @@ namespace OpenMS void RawMSSignalSimulation::loadContaminants() { // contaminants: - String contaminants_file = param_.getValue("contaminants:file"); + String contaminants_file = param_.getValue("contaminants:file").toString(); if (contaminants_file.trim().size() != 0) { @@ -505,7 +505,7 @@ namespace OpenMS createContaminants_(c_map, experiment, experiment_ct); } - if ((String)param_.getValue("ionization_type") == "MALDI") + if (param_.getValue("ionization_type") == "MALDI") { addBaseLine_(experiment, minimal_mz_measurement_limit); } @@ -937,7 +937,7 @@ namespace OpenMS if (!contaminants_loaded_) loadContaminants(); - IONIZATIONMETHOD this_im = (String)param_.getValue("ionization_type") == "ESI" ? IM_ESI : IM_MALDI; + IONIZATIONMETHOD this_im = param_.getValue("ionization_type") == "ESI" ? IM_ESI : IM_MALDI; c_map.clear(true); Size out_of_range_RT(0), out_of_range_MZ(0); diff --git a/src/openms/source/SIMULATION/RawTandemMSSignalSimulation.cpp b/src/openms/source/SIMULATION/RawTandemMSSignalSimulation.cpp index e7b34fe46a9..a4e69870f35 100644 --- a/src/openms/source/SIMULATION/RawTandemMSSignalSimulation.cpp +++ b/src/openms/source/SIMULATION/RawTandemMSSignalSimulation.cpp @@ -72,7 +72,7 @@ namespace OpenMS { // Tandem MS params defaults_.setValue("status", "disabled", "Create Tandem-MS scans?"); - defaults_.setValidStrings("status", ListUtils::create("disabled,precursor,MS^E")); + defaults_.setValidStrings("status", {"disabled","precursor","MS^E"}); subsections_.push_back("Precursor:"); defaults_.insert("Precursor:", OfflinePrecursorIonSelection().getDefaults()); @@ -82,7 +82,7 @@ namespace OpenMS defaults_.setMaxInt("Precursor:charge_filter", 5); defaults_.setValue("MS_E:add_single_spectra", "false", "If true, the MS2 spectra for each peptide signal are included in the output (might be a lot). They will have a meta value 'MSE_DebugSpectrum' attached, so they can be filtered out. Native MS_E spectra will have 'MSE_Spectrum' instead."); - defaults_.setValidStrings("MS_E:add_single_spectra", ListUtils::create("true,false")); + defaults_.setValidStrings("MS_E:add_single_spectra", {"true","false"}); defaults_.setValue("tandem_mode", 0, "Algorithm to generate the tandem-MS spectra. 0 - fixed intensities, 1 - SVC prediction (abundant/missing), 2 - SVR prediction of peak intensity \n"); defaults_.setMinInt("tandem_mode", 0); defaults_.setMaxInt("tandem_mode", 2); @@ -97,7 +97,7 @@ namespace OpenMS // sync'ed Param (also appears in IonizationSimulation) defaults_.setValue("ionization_type", "ESI", "Type of Ionization (MALDI or ESI)"); - defaults_.setValidStrings("ionization_type", ListUtils::create("MALDI,ESI")); + defaults_.setValidStrings("ionization_type", {"MALDI","ESI"}); defaultsToParam_(); } @@ -123,7 +123,7 @@ namespace OpenMS // if SVR or SVC shall be used if (tandem_mode) { - String svm_filename = param_.getValue("svm_model_set_file"); + String svm_filename = param_.getValue("svm_model_set_file").toString(); if (!File::readable(svm_filename)) // look in OPENMS_DATA_PATH { svm_filename = File::find(svm_filename); @@ -209,7 +209,7 @@ namespace OpenMS } // creating the MS^E scan: - bool add_debug_spectra = static_cast(param_.getValue("MS_E:add_single_spectra")) == "true"; + bool add_debug_spectra = param_.getValue("MS_E:add_single_spectra").toBool(); for (Size i = 0; i < experiment.size(); ++i) // create MS2 for every MS scan { // check which features elute in the current MS scan @@ -288,7 +288,7 @@ namespace OpenMS param.remove("charge_filter"); ps.setParameters(param); // different selection strategies for MALDI and ESI - bool is_MALDI = static_cast(param_.getValue("ionization_type")) == "MALDI"; + bool is_MALDI = param_.getValue("ionization_type") == "MALDI"; // fill 'ms2' with precursor information, but leave spectra empty ps.makePrecursorSelectionForKnownLCMSMap(features, experiment, ms2, qs_set, is_MALDI); @@ -311,7 +311,7 @@ namespace OpenMS // if SVR or SVC shall be used if (tandem_mode) { - String svm_filename = param_.getValue("svm_model_set_file"); + String svm_filename = param_.getValue("svm_model_set_file").toString(); if (!File::readable(svm_filename)) // look in OPENMS_DATA_PATH { svm_filename = File::find(svm_filename); diff --git a/src/openms/source/SYSTEM/ExternalProcess.cpp b/src/openms/source/SYSTEM/ExternalProcess.cpp index acac572ebba..841e2f071d3 100644 --- a/src/openms/source/SYSTEM/ExternalProcess.cpp +++ b/src/openms/source/SYSTEM/ExternalProcess.cpp @@ -73,13 +73,13 @@ namespace OpenMS } - ExternalProcess::RETURNSTATE ExternalProcess::run(const QString& exe, const QStringList& args, const QString& working_dir, const bool verbose) + ExternalProcess::RETURNSTATE ExternalProcess::run(const QString& exe, const QStringList& args, const QString& working_dir, const bool verbose, IO_MODE io_mode) { String error_msg; - return run(exe, args, working_dir, verbose, error_msg); + return run(exe, args, working_dir, verbose, error_msg, io_mode); } - ExternalProcess::RETURNSTATE ExternalProcess::run(const QString& exe, const QStringList& args, const QString& working_dir, const bool verbose, String& error_msg) + ExternalProcess::RETURNSTATE ExternalProcess::run(const QString& exe, const QStringList& args, const QString& working_dir, const bool verbose, String& error_msg, IO_MODE io_mode) { error_msg.clear(); if (!working_dir.isEmpty()) @@ -89,7 +89,24 @@ namespace OpenMS if (verbose) callbackStdOut_("Running: " + (QStringList() << exe << args).join(' ') + '\n'); - qp_->start(exe, args); + // Map IO_MODE enum value to QIODevice value + QIODevice::OpenModeFlag mode; + switch (io_mode) + { + case IO_MODE::NO_IO: + mode = QIODevice::NotOpen; + break; + case IO_MODE::READ_ONLY: + mode = QIODevice::ReadOnly; + break; + case IO_MODE::WRITE_ONLY: + mode = QIODevice::WriteOnly; + break; + default: + mode = QIODevice::ReadWrite; + } + + qp_->start(exe, args, mode); if (!(qp_->waitForStarted())) { error_msg = "Process '" + exe + "' failed to start. Does it exist? Is it executable?"; @@ -129,10 +146,12 @@ namespace OpenMS //std::cout << s << "\n"; callbackStdOut_(s); } + void ExternalProcess::processStdErr_() { String s(QString(qp_->readAllStandardError())); //std::cout << s << "\n"; callbackStdErr_(s); } + } // ns OpenMS diff --git a/src/openms/source/SYSTEM/File.cpp b/src/openms/source/SYSTEM/File.cpp index 5732251bf9b..303abbcb58f 100644 --- a/src/openms/source/SYSTEM/File.cpp +++ b/src/openms/source/SYSTEM/File.cpp @@ -92,44 +92,39 @@ namespace OpenMS String File::getExecutablePath() { // see http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe/1024937#1024937 for more OS' (if needed) - static String spath = ""; - static bool path_checked = false; - - // short route. Only inquire the path once. The result will be the same every time. - if (path_checked) return spath; + // Use immediately evaluated lambda to protect static variable from concurrent access. + static String spath = [&]() -> String { + String rpath = ""; - char path[1024]; + char path[1024]; #ifdef OPENMS_WINDOWSPLATFORM - int size = sizeof(path); - if (GetModuleFileName(NULL, path, size)) + int size = sizeof(path); + if (GetModuleFileName(NULL, path, size)) #elif defined(__APPLE__) - uint size = sizeof(path); - if (_NSGetExecutablePath(path, &size) == 0) + uint size = sizeof(path); + if (_NSGetExecutablePath(path, &size) == 0) #else // LINUX - int size = sizeof(path); - int ch = readlink("/proc/self/exe", path, size); - if (ch != -1) + int size = sizeof(path); + int ch = readlink("/proc/self/exe", path, size); + if (ch != -1) #endif - { - spath = File::path(String(path)); - if (File::exists(spath)) // check if directory exists - { - // ensure path ends with a "/", such that we can just write path + "ToolX", and to not worry about if its empty or a path. - spath.ensureLastChar('/'); - } - else - { - std::cerr << "Path extracted from Executable Path does not exist! Returning empty string!\n"; - spath = ""; - } - } - else - { - std::cerr << "Cannot get Executable Path! Not using a path prefix!\n"; - } + { + rpath = File::path(String(path)); + if (File::exists(rpath)) // check if directory exists + { + // ensure path ends with a "/", such that we can just write path + "ToolX", and to not worry about if its empty or a path. + rpath.ensureLastChar('/'); + } else { + std::cerr << "Path extracted from Executable Path does not exist! Returning empty string!\n"; + rpath = ""; + } + } else { + std::cerr << "Cannot get Executable Path! Not using a path prefix!\n"; + } - path_checked = true; // enable short route for next run + return rpath; + }(); return spath; } @@ -447,7 +442,7 @@ namespace OpenMS #else pid = (String)getpid(); #endif - static int number = 0; + static std::atomic_int number = 0; return now.getDate().remove('-') + "_" + now.getTime().remove(':') + "_" + (include_hostname ? String(QHostInfo::localHostName()) + "_" : "") + pid + "_" + (++number); } @@ -516,7 +511,7 @@ namespace OpenMS std::cerr << " The environment variable 'OPENMS_DATA_PATH' currently points to '" << p << "', which is incorrect!\n"; } #ifdef OPENMS_WINDOWSPLATFORM - String share_dir = "c:\\Program Files\\OpenMS\\share\\OpenMS"; + String share_dir = R"(c:\Program Files\OpenMS\share\OpenMS)"; #else String share_dir = "/usr/share/OpenMS"; #endif @@ -548,9 +543,9 @@ namespace OpenMS { dir = getenv("OPENMS_TMPDIR"); } - else if (p.exists("temp_dir") && String(p.getValue("temp_dir")).trim() != "") + else if (p.exists("temp_dir") && String(p.getValue("temp_dir").toString()).trim() != "") { - dir = p.getValue("temp_dir"); + dir = p.getValue("temp_dir").toString(); } else { @@ -568,9 +563,9 @@ namespace OpenMS { dir = getenv("OPENMS_HOME_PATH"); } - else if (p.exists("home_dir") && String(p.getValue("home_dir")).trim() != "") + else if (p.exists("home_dir") && String(p.getValue("home_dir").toString()).trim() != "") { - dir = p.getValue("home_dir"); + dir = p.getValue("home_dir").toString(); } else { @@ -586,7 +581,7 @@ namespace OpenMS String full_db_name; try { - full_db_name = find(db_name, sys_p.getValue("id_db_dir")); + full_db_name = find(db_name, ListUtils::toStringList(sys_p.getValue("id_db_dir"))); OPENMS_LOG_INFO << "Augmenting database name '" << db_name << "' with path given in 'OpenMS.ini:id_db_dir'. Full name is now: '" << full_db_name << "'" << std::endl; } catch (Exception::FileNotFound& e) @@ -656,7 +651,7 @@ namespace OpenMS p.setValue("version", VersionInfo::getVersion()); p.setValue("home_dir", ""); // only active when user enters something in this value p.setValue("temp_dir", ""); // only active when user enters something in this value - p.setValue("id_db_dir", ListUtils::create(""), + p.setValue("id_db_dir", std::vector(), String("Default directory for FASTA and psq files used as databased for id engines. ") + \ "This allows you to specify just the filename of the DB in the " + \ "respective TOPP tool, and the database will be searched in the directories specified here " + \ @@ -770,12 +765,14 @@ namespace OpenMS const String& File::TemporaryFiles_::newFile() { String s = getTempDirectory().ensureLastChar('/') + getUniqueName(); + std::lock_guard _(mtx_); filenames_.push_back(s); return filenames_.back(); } File::TemporaryFiles_::~TemporaryFiles_() { + std::lock_guard _(mtx_); for (Size i = 0; i < filenames_.size(); ++i) { if (File::exists(filenames_[i]) && !File::remove(filenames_[i])) diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/BiGaussFitter1D.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/BiGaussFitter1D.cpp index 2a9cef5d9a7..d15e89317d3 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/BiGaussFitter1D.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/BiGaussFitter1D.cpp @@ -42,8 +42,8 @@ namespace OpenMS { setName(getProductName()); - defaults_.setValue("statistics:variance1", 1.0, "Variance of the first gaussian, used for the lower half of the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:variance2", 1.0, "Variance of the second gaussian, used for the upper half of the model.", ListUtils::create("advanced")); + defaults_.setValue("statistics:variance1", 1.0, "Variance of the first gaussian, used for the lower half of the model.", {"advanced"}); + defaults_.setValue("statistics:variance2", 1.0, "Variance of the second gaussian, used for the upper half of the model.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/BiGaussModel.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/BiGaussModel.cpp index c94b2d629c0..65f6d7baed3 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/BiGaussModel.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/BiGaussModel.cpp @@ -41,11 +41,11 @@ namespace OpenMS { setName(getProductName()); - defaults_.setValue("bounding_box:min", 0.0, "Lower end of bounding box enclosing the data used to fit the model.", ListUtils::create("advanced")); - defaults_.setValue("bounding_box:max", 1.0, "Upper end of bounding box enclosing the data used to fit the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:mean", 0.0, "Centroid position of the model, this also separates both halves of the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:variance1", 1.0, "Variance of the first gaussian, used for the lower half of the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:variance2", 1.0, "Variance of the second gaussian, used for the upper half of the model.", ListUtils::create("advanced")); + defaults_.setValue("bounding_box:min", 0.0, "Lower end of bounding box enclosing the data used to fit the model.", {"advanced"}); + defaults_.setValue("bounding_box:max", 1.0, "Upper end of bounding box enclosing the data used to fit the model.", {"advanced"}); + defaults_.setValue("statistics:mean", 0.0, "Centroid position of the model, this also separates both halves of the model.", {"advanced"}); + defaults_.setValue("statistics:variance1", 1.0, "Variance of the first gaussian, used for the lower half of the model.", {"advanced"}); + defaults_.setValue("statistics:variance2", 1.0, "Variance of the second gaussian, used for the upper half of the model.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ElutionModelFitter.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ElutionModelFitter.cpp index f132ee268e6..040050ed742 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ElutionModelFitter.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ElutionModelFitter.cpp @@ -46,8 +46,8 @@ using namespace std; ElutionModelFitter::ElutionModelFitter(): DefaultParamHandler("ElutionModelFitter") { - vector truefalse = ListUtils::create("true,false"); - vector advanced(1, "advanced"); + std::vector truefalse = {"true","false"}; + std::vector advanced = {"advanced"}; defaults_.setValue("asymmetric", "false", "Fit an asymmetric (exponential-Gaussian hybrid) model? By default a symmetric (Gaussian) model is used."); defaults_.setValidStrings("asymmetric", truefalse); diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/EmgModel.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/EmgModel.cpp index 01d8cece415..fcf374a3498 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/EmgModel.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/EmgModel.cpp @@ -43,14 +43,14 @@ namespace OpenMS { setName(getProductName()); - defaults_.setValue("bounding_box:min", 0.0f, "Lower end of bounding box enclosing the data used to fit the model.", ListUtils::create("advanced")); - defaults_.setValue("bounding_box:max", 1.0f, "Upper end of bounding box enclosing the data used to fit the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:mean", 0.0f, "Centroid position of the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:variance", 1.0f, "The variance of the model.", ListUtils::create("advanced")); - defaults_.setValue("emg:height", 100000.0f, "Height of the exponentially modified Gaussian.", ListUtils::create("advanced")); - defaults_.setValue("emg:width", 5.0f, "Width of the exponentially modified Gaussian.", ListUtils::create("advanced")); - defaults_.setValue("emg:symmetry", 5.0f, "Symmetry of the exponentially modified Gaussian.", ListUtils::create("advanced")); - defaults_.setValue("emg:retention", 1200.0f, "Retention time of the exponentially modified Gaussian.", ListUtils::create("advanced")); + defaults_.setValue("bounding_box:min", 0.0f, "Lower end of bounding box enclosing the data used to fit the model.", {"advanced"}); + defaults_.setValue("bounding_box:max", 1.0f, "Upper end of bounding box enclosing the data used to fit the model.", {"advanced"}); + defaults_.setValue("statistics:mean", 0.0f, "Centroid position of the model.", {"advanced"}); + defaults_.setValue("statistics:variance", 1.0f, "The variance of the model.", {"advanced"}); + defaults_.setValue("emg:height", 100000.0f, "Height of the exponentially modified Gaussian.", {"advanced"}); + defaults_.setValue("emg:width", 5.0f, "Width of the exponentially modified Gaussian.", {"advanced"}); + defaults_.setValue("emg:symmetry", 5.0f, "Symmetry of the exponentially modified Gaussian.", {"advanced"}); + defaults_.setValue("emg:retention", 1200.0f, "Retention time of the exponentially modified Gaussian.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ExtendedIsotopeFitter1D.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ExtendedIsotopeFitter1D.cpp index b809d9d29fe..a3a101d6bcb 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ExtendedIsotopeFitter1D.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ExtendedIsotopeFitter1D.cpp @@ -44,12 +44,12 @@ namespace OpenMS { setName(getProductName()); - defaults_.setValue("statistics:variance", 1.0, "Variance of the model.", ListUtils::create("advanced")); - defaults_.setValue("charge", 1, "Charge state of the model.", ListUtils::create("advanced")); - defaults_.setValue("isotope:stdev", 0.1, "Standard deviation of gaussian applied to the averagine isotopic pattern to simulate the inaccuracy of the mass spectrometer.", ListUtils::create("advanced")); - defaults_.setValue("isotope:monoisotopic_mz", 1.0, "Monoisotopic m/z of the model.", ListUtils::create("advanced")); - defaults_.setValue("isotope:maximum", 100, "Maximum isotopic rank to be considered.", ListUtils::create("advanced")); - defaults_.setValue("interpolation_step", 0.2, "Sampling rate for the interpolation of the model function.", ListUtils::create("advanced")); + defaults_.setValue("statistics:variance", 1.0, "Variance of the model.", {"advanced"}); + defaults_.setValue("charge", 1, "Charge state of the model.", {"advanced"}); + defaults_.setValue("isotope:stdev", 0.1, "Standard deviation of gaussian applied to the averagine isotopic pattern to simulate the inaccuracy of the mass spectrometer.", {"advanced"}); + defaults_.setValue("isotope:monoisotopic_mz", 1.0, "Monoisotopic m/z of the model.", {"advanced"}); + defaults_.setValue("isotope:maximum", 100, "Maximum isotopic rank to be considered.", {"advanced"}); + defaults_.setValue("interpolation_step", 0.2, "Sampling rate for the interpolation of the model function.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ExtendedIsotopeModel.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ExtendedIsotopeModel.cpp index 24edbd967a8..5f50271c82e 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ExtendedIsotopeModel.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/ExtendedIsotopeModel.cpp @@ -47,18 +47,18 @@ namespace OpenMS { setName(getProductName()); - defaults_.setValue("averagines:C", 0.04443989f, "Number of C atoms per Dalton of mass.", ListUtils::create("advanced")); - defaults_.setValue("averagines:H", 0.06981572f, "Number of H atoms per Dalton of mass.", ListUtils::create("advanced")); - defaults_.setValue("averagines:N", 0.01221773f, "Number of N atoms per Dalton of mass.", ListUtils::create("advanced")); - defaults_.setValue("averagines:O", 0.01329399f, "Number of O atoms per Dalton of mass.", ListUtils::create("advanced")); - defaults_.setValue("averagines:S", 0.00037525f, "Number of S atoms per Dalton of mass.", ListUtils::create("advanced")); - - defaults_.setValue("isotope:trim_right_cutoff", 0.001, "Cutoff in averagine distribution, trailing isotopes below this relative intensity are not considered.", ListUtils::create("advanced")); - defaults_.setValue("isotope:maximum", 100, "Maximum isotopic rank to be considered.", ListUtils::create("advanced")); - defaults_.setValue("isotope:distance", 1.000495, "Distance between consecutive isotopic peaks.", ListUtils::create("advanced")); - defaults_.setValue("isotope:stdev", 0.1, "Standard deviation of gaussian applied to the averagine isotopic pattern to simulate the inaccuracy of the mass spectrometer.", ListUtils::create("advanced")); - defaults_.setValue("charge", 1, "Charge state of the model.", ListUtils::create("advanced")); - defaults_.setValue("isotope:monoisotopic_mz", 1.0, "Monoisotopic m/z of the model.", ListUtils::create("advanced")); + defaults_.setValue("averagines:C", 0.04443989f, "Number of C atoms per Dalton of mass.", {"advanced"}); + defaults_.setValue("averagines:H", 0.06981572f, "Number of H atoms per Dalton of mass.", {"advanced"}); + defaults_.setValue("averagines:N", 0.01221773f, "Number of N atoms per Dalton of mass.", {"advanced"}); + defaults_.setValue("averagines:O", 0.01329399f, "Number of O atoms per Dalton of mass.", {"advanced"}); + defaults_.setValue("averagines:S", 0.00037525f, "Number of S atoms per Dalton of mass.", {"advanced"}); + + defaults_.setValue("isotope:trim_right_cutoff", 0.001, "Cutoff in averagine distribution, trailing isotopes below this relative intensity are not considered.", {"advanced"}); + defaults_.setValue("isotope:maximum", 100, "Maximum isotopic rank to be considered.", {"advanced"}); + defaults_.setValue("isotope:distance", 1.000495, "Distance between consecutive isotopic peaks.", {"advanced"}); + defaults_.setValue("isotope:stdev", 0.1, "Standard deviation of gaussian applied to the averagine isotopic pattern to simulate the inaccuracy of the mass spectrometer.", {"advanced"}); + defaults_.setValue("charge", 1, "Charge state of the model.", {"advanced"}); + defaults_.setValue("isotope:monoisotopic_mz", 1.0, "Monoisotopic m/z of the model.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmIsotopeWavelet.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmIsotopeWavelet.cpp index 2ef17ebedc7..4b2eb693407 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmIsotopeWavelet.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmIsotopeWavelet.cpp @@ -53,23 +53,23 @@ namespace OpenMS "Depending on the dynamic range of your spectra, suitable value ranges include: -1, [0:10], and if your data " "features even very high intensity values, t can also adopt values up to around 30. " "Please note that this parameter is not of an integer type, s.t. you can also use t:=0.1, e.g."); - this->defaults_.setValue("intensity_type", "ref", "Determines the intensity type returned for the identified features. 'ref' (default) returns the sum of the intensities of each isotopic peak within an isotope pattern. 'trans' refers to the intensity of the monoisotopic peak within the wavelet transform. 'corrected' refers also to the transformed intensity with an attempt to remove the effects of the convolution. While the latter ones might be preferable for qualitative analyses, 'ref' might be the best option to obtain quantitative results. Please note that intensity values might be spoiled (in particular for the option 'ref'), as soon as patterns overlap (see also the explanations given in the class documentation of FeatureFinderAlgorihtmIsotopeWavelet).", ListUtils::create("advanced")); - this->defaults_.setValidStrings("intensity_type", ListUtils::create("ref,trans,corrected")); + this->defaults_.setValue("intensity_type", "ref", "Determines the intensity type returned for the identified features. 'ref' (default) returns the sum of the intensities of each isotopic peak within an isotope pattern. 'trans' refers to the intensity of the monoisotopic peak within the wavelet transform. 'corrected' refers also to the transformed intensity with an attempt to remove the effects of the convolution. While the latter ones might be preferable for qualitative analyses, 'ref' might be the best option to obtain quantitative results. Please note that intensity values might be spoiled (in particular for the option 'ref'), as soon as patterns overlap (see also the explanations given in the class documentation of FeatureFinderAlgorihtmIsotopeWavelet).", {"advanced"}); + this->defaults_.setValidStrings("intensity_type", {"ref","trans","corrected"}); this->defaults_.setValue("check_ppm", "false", "Enables/disables a ppm test vs. the averagine model, i.e. " - "potential peptide masses are checked for plausibility. In addition, a heuristic correcting potential mass shifts induced by the wavelet is applied.", ListUtils::create("advanced")); - this->defaults_.setValidStrings("check_ppm", ListUtils::create("true,false")); + "potential peptide masses are checked for plausibility. In addition, a heuristic correcting potential mass shifts induced by the wavelet is applied.", {"advanced"}); + this->defaults_.setValidStrings("check_ppm", {"true","false"}); this->defaults_.setValue("hr_data", "false", "Must be true in case of high-resolution data, i.e. " "for spectra featuring large m/z-gaps (present in FTICR and Orbitrap data, e.g.). Please check " "a single MS scan out of your recording, if you are unsure."); - this->defaults_.setValidStrings("hr_data", ListUtils::create("true,false")); + this->defaults_.setValidStrings("hr_data", {"true","false"}); this->defaults_.setValue("sweep_line:rt_votes_cutoff", 5, "Defines the minimum number of " - "subsequent scans where a pattern must occur to be considered as a feature.", ListUtils::create("advanced")); + "subsequent scans where a pattern must occur to be considered as a feature.", {"advanced"}); this->defaults_.setMinInt("sweep_line:rt_votes_cutoff", 0); this->defaults_.setValue("sweep_line:rt_interleave", 1, "Defines the maximum number of " - "scans (w.r.t. rt_votes_cutoff) where an expected pattern is missing. There is usually no reason to change the default value.", ListUtils::create("advanced")); + "scans (w.r.t. rt_votes_cutoff) where an expected pattern is missing. There is usually no reason to change the default value.", {"advanced"}); this->defaults_.setMinInt("sweep_line:rt_interleave", 0); this->defaultsToParam_(); @@ -305,9 +305,9 @@ namespace OpenMS RT_votes_cutoff_ = this->param_.getValue("sweep_line:rt_votes_cutoff"); RT_interleave_ = this->param_.getValue("sweep_line:rt_interleave"); IsotopeWavelet::setMaxCharge(max_charge_); - check_PPMs_ = ((String)(this->param_.getValue("check_ppm")) == "true"); - hr_data_ = ((String)(this->param_.getValue("hr_data")) == "true"); - intensity_type_ = ((String)(this->param_.getValue("intensity_type"))); + check_PPMs_ = this->param_.getValue("check_ppm").toBool(); + hr_data_ = this->param_.getValue("hr_data").toBool(); + intensity_type_ = this->param_.getValue("intensity_type").toString(); } } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmMRM.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmMRM.cpp index 195d3124343..af586d3ba24 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmMRM.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmMRM.cpp @@ -50,18 +50,18 @@ namespace OpenMS { defaults_.setValue("min_rt_distance", 10.0, "Minimal distance of MRM features in seconds."); defaults_.setMinFloat("min_rt_distance", 0.0); - defaults_.setValue("min_num_peaks_per_feature", 5, "Minimal number of peaks which are needed for a single feature", ListUtils::create("advanced")); + defaults_.setValue("min_num_peaks_per_feature", 5, "Minimal number of peaks which are needed for a single feature", {"advanced"}); defaults_.setMinInt("min_num_peaks_per_feature", 1); defaults_.setValue("min_signal_to_noise_ratio", 2.0, "Minimal S/N ratio a peak must have to be taken into account. Set to zero if the MRM-traces contains mostly signals, and no noise."); defaults_.setMinFloat("min_signal_to_noise_ratio", 0); - defaults_.setValue("write_debug_files", "false", "If set to true, for each feature a plot will be created, in the subdirectory 'debug'", ListUtils::create("advanced")); - defaults_.setValidStrings("write_debug_files", ListUtils::create("true,false")); + defaults_.setValue("write_debug_files", "false", "If set to true, for each feature a plot will be created, in the subdirectory 'debug'", {"advanced"}); + defaults_.setValidStrings("write_debug_files", {"true","false"}); - defaults_.setValue("resample_traces", "false", "If set to true, each trace, which is in this case a part of the MRM monitoring trace with signal is resampled, using the minimal distance of two data points in RT dimension", ListUtils::create("advanced")); - defaults_.setValidStrings("resample_traces", ListUtils::create("true,false")); + defaults_.setValue("resample_traces", "false", "If set to true, each trace, which is in this case a part of the MRM monitoring trace with signal is resampled, using the minimal distance of two data points in RT dimension", {"advanced"}); + defaults_.setValidStrings("resample_traces", {"true","false"}); - defaults_.setValue("write_debuginfo", "false", "If set to true, debug messages are written, the output can be somewhat lengthy.", ListUtils::create("advanced")); - defaults_.setValidStrings("write_debuginfo", ListUtils::create("true,false")); + defaults_.setValue("write_debuginfo", "false", "If set to true, debug messages are written, the output can be somewhat lengthy.", {"advanced"}); + defaults_.setValidStrings("write_debuginfo", {"true","false"}); this->defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmPicked.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmPicked.cpp index 14531d308e5..b58493a704c 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmPicked.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmPicked.cpp @@ -61,7 +61,7 @@ namespace OpenMS { //debugging defaults_.setValue("debug", "false", "When debug mode is activated, several files with intermediate results are written to the folder 'debug' (do not use in parallel mode)."); - defaults_.setValidStrings("debug", ListUtils::create("true,false")); + defaults_.setValidStrings("debug", {"true","false"}); //intensity defaults_.setValue("intensity:bins", 10, "Number of bins per dimension (RT and m/z). The higher this value, the more local the intensity significance score is.\nThis parameter should be decreased, if the algorithm is used on small regions of a map."); defaults_.setMinInt("intensity:bins", 1); @@ -83,22 +83,22 @@ namespace OpenMS defaults_.setMinInt("isotopic_pattern:charge_high", 1); defaults_.setValue("isotopic_pattern:mz_tolerance", 0.03, "Tolerated m/z deviation from the theoretical isotopic pattern.\nIt should be larger than the m/z resolution of the instrument.\nThis value must be smaller than that 1/charge_high!"); defaults_.setMinFloat("isotopic_pattern:mz_tolerance", 0.0); - defaults_.setValue("isotopic_pattern:intensity_percentage", 10.0, "Isotopic peaks that contribute more than this percentage to the overall isotope pattern intensity must be present.", ListUtils::create("advanced")); + defaults_.setValue("isotopic_pattern:intensity_percentage", 10.0, "Isotopic peaks that contribute more than this percentage to the overall isotope pattern intensity must be present.", {"advanced"}); defaults_.setMinFloat("isotopic_pattern:intensity_percentage", 0.0); defaults_.setMaxFloat("isotopic_pattern:intensity_percentage", 100.0); - defaults_.setValue("isotopic_pattern:intensity_percentage_optional", 0.1, "Isotopic peaks that contribute more than this percentage to the overall isotope pattern intensity can be missing.", ListUtils::create("advanced")); + defaults_.setValue("isotopic_pattern:intensity_percentage_optional", 0.1, "Isotopic peaks that contribute more than this percentage to the overall isotope pattern intensity can be missing.", {"advanced"}); defaults_.setMinFloat("isotopic_pattern:intensity_percentage_optional", 0.0); defaults_.setMaxFloat("isotopic_pattern:intensity_percentage_optional", 100.0); - defaults_.setValue("isotopic_pattern:optional_fit_improvement", 2.0, "Minimal percental improvement of isotope fit to allow leaving out an optional peak.", ListUtils::create("advanced")); + defaults_.setValue("isotopic_pattern:optional_fit_improvement", 2.0, "Minimal percental improvement of isotope fit to allow leaving out an optional peak.", {"advanced"}); defaults_.setMinFloat("isotopic_pattern:optional_fit_improvement", 0.0); defaults_.setMaxFloat("isotopic_pattern:optional_fit_improvement", 100.0); - defaults_.setValue("isotopic_pattern:mass_window_width", 25.0, "Window width in Dalton for precalculation of estimated isotope distributions.", ListUtils::create("advanced")); + defaults_.setValue("isotopic_pattern:mass_window_width", 25.0, "Window width in Dalton for precalculation of estimated isotope distributions.", {"advanced"}); defaults_.setMinFloat("isotopic_pattern:mass_window_width", 1.0); defaults_.setMaxFloat("isotopic_pattern:mass_window_width", 200.0); - defaults_.setValue("isotopic_pattern:abundance_12C", 98.93, "Rel. abundance of the light carbon. Modify if labeled.", ListUtils::create("advanced")); + defaults_.setValue("isotopic_pattern:abundance_12C", 98.93, "Rel. abundance of the light carbon. Modify if labeled.", {"advanced"}); defaults_.setMinFloat("isotopic_pattern:abundance_12C", 0.0); defaults_.setMaxFloat("isotopic_pattern:abundance_12C", 100.0); - defaults_.setValue("isotopic_pattern:abundance_14N", 99.632, "Rel. abundance of the light nitrogen. Modify if labeled.", ListUtils::create("advanced")); + defaults_.setValue("isotopic_pattern:abundance_14N", 99.632, "Rel. abundance of the light nitrogen. Modify if labeled.", {"advanced"}); defaults_.setMinFloat("isotopic_pattern:abundance_14N", 0.0); defaults_.setMaxFloat("isotopic_pattern:abundance_14N", 100.0); @@ -109,31 +109,31 @@ namespace OpenMS defaults_.setMaxFloat("seed:min_score", 1.0); defaults_.setSectionDescription("seed", "Settings that determine which peaks are considered a seed"); //Fitting settings - defaults_.setValue("fit:max_iterations", 500, "Maximum number of iterations of the fit.", ListUtils::create("advanced")); + defaults_.setValue("fit:max_iterations", 500, "Maximum number of iterations of the fit.", {"advanced"}); defaults_.setMinInt("fit:max_iterations", 1); defaults_.setSectionDescription("fit", "Settings for the model fitting"); //Feature settings defaults_.setValue("feature:min_score", 0.7, "Feature score threshold for a feature to be reported.\nThe feature score is the geometric mean of the average relative deviation and the correlation between the model and the observed peaks."); defaults_.setMinFloat("feature:min_score", 0.0); defaults_.setMaxFloat("feature:min_score", 1.0); - defaults_.setValue("feature:min_isotope_fit", 0.8, "Minimum isotope fit of the feature before model fitting.", ListUtils::create("advanced")); + defaults_.setValue("feature:min_isotope_fit", 0.8, "Minimum isotope fit of the feature before model fitting.", {"advanced"}); defaults_.setMinFloat("feature:min_isotope_fit", 0.0); defaults_.setMaxFloat("feature:min_isotope_fit", 1.0); - defaults_.setValue("feature:min_trace_score", 0.5, "Trace score threshold.\nTraces below this threshold are removed after the model fitting.\nThis parameter is important for features that overlap in m/z dimension.", ListUtils::create("advanced")); + defaults_.setValue("feature:min_trace_score", 0.5, "Trace score threshold.\nTraces below this threshold are removed after the model fitting.\nThis parameter is important for features that overlap in m/z dimension.", {"advanced"}); defaults_.setMinFloat("feature:min_trace_score", 0.0); defaults_.setMaxFloat("feature:min_trace_score", 1.0); - defaults_.setValue("feature:min_rt_span", 0.333, "Minimum RT span in relation to extended area that has to remain after model fitting.", ListUtils::create("advanced")); + defaults_.setValue("feature:min_rt_span", 0.333, "Minimum RT span in relation to extended area that has to remain after model fitting.", {"advanced"}); defaults_.setMinFloat("feature:min_rt_span", 0.0); defaults_.setMaxFloat("feature:min_rt_span", 1.0); - defaults_.setValue("feature:max_rt_span", 2.5, "Maximum RT span in relation to extended area that the model is allowed to have.", ListUtils::create("advanced")); + defaults_.setValue("feature:max_rt_span", 2.5, "Maximum RT span in relation to extended area that the model is allowed to have.", {"advanced"}); defaults_.setMinFloat("feature:max_rt_span", 0.5); - defaults_.setValue("feature:rt_shape", "symmetric", "Choose model used for RT profile fitting. If set to symmetric a gauss shape is used, in case of asymmetric an EGH shape is used.", ListUtils::create("advanced")); - defaults_.setValidStrings("feature:rt_shape", ListUtils::create("symmetric,asymmetric")); - defaults_.setValue("feature:max_intersection", 0.35, "Maximum allowed intersection of features.", ListUtils::create("advanced")); + defaults_.setValue("feature:rt_shape", "symmetric", "Choose model used for RT profile fitting. If set to symmetric a gauss shape is used, in case of asymmetric an EGH shape is used.", {"advanced"}); + defaults_.setValidStrings("feature:rt_shape", {"symmetric","asymmetric"}); + defaults_.setValue("feature:max_intersection", 0.35, "Maximum allowed intersection of features.", {"advanced"}); defaults_.setMinFloat("feature:max_intersection", 0.0); defaults_.setMaxFloat("feature:max_intersection", 1.0); defaults_.setValue("feature:reported_mz", "monoisotopic", "The mass type that is reported for features.\n'maximum' returns the m/z value of the highest mass trace.\n'average' returns the intensity-weighted average m/z value of all contained peaks.\n'monoisotopic' returns the monoisotopic m/z value derived from the fitted isotope model."); - defaults_.setValidStrings("feature:reported_mz", ListUtils::create("maximum,average,monoisotopic")); + defaults_.setValidStrings("feature:reported_mz", {"maximum","average","monoisotopic"}); defaults_.setSectionDescription("feature", "Settings for the features (intensity, quality assessment, ...)"); //user-specified seed settings defaults_.setValue("user-seed:rt_tolerance", 5.0, "Allowed RT deviation of seeds from the user-specified seed position."); @@ -145,7 +145,7 @@ namespace OpenMS defaults_.setMaxFloat("user-seed:min_score", 1.0); defaults_.setSectionDescription("user-seed", "Settings for user-specified seeds."); //debug settings - defaults_.setValue("debug:pseudo_rt_shift", 500.0, "Pseudo RT shift used when .", ListUtils::create("advanced")); + defaults_.setValue("debug:pseudo_rt_shift", 500.0, "Pseudo RT shift used when .", {"advanced"}); defaults_.setMinFloat("debug:pseudo_rt_shift", 1.0); this->defaultsToParam_(); } @@ -247,7 +247,7 @@ namespace OpenMS } } - debug_ = ((String)(param_.getValue("debug")) == "true"); + debug_ = param_.getValue("debug").toBool(); //clean up / create folders for debug information if (debug_) { @@ -1031,7 +1031,7 @@ namespace OpenMS min_rt_span_ = param_.getValue("feature:min_rt_span"); max_rt_span_ = param_.getValue("feature:max_rt_span"); max_feature_intersection_ = param_.getValue("feature:max_intersection"); - reported_mz_ = param_.getValue("feature:reported_mz"); + reported_mz_ = param_.getValue("feature:reported_mz").toString(); } /// Writes the abort reason to the log file and counts occurrences for each reason diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderIdentificationAlgorithm.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderIdentificationAlgorithm.cpp index 6e9c4192709..2f9ff43dfa7 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderIdentificationAlgorithm.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderIdentificationAlgorithm.cpp @@ -66,12 +66,12 @@ namespace OpenMS FeatureFinderIdentificationAlgorithm::FeatureFinderIdentificationAlgorithm() : DefaultParamHandler("FeatureFinderIdentificationAlgorithm") { - StringList output_file_tags; + std::vector output_file_tags; output_file_tags.push_back("output file"); defaults_.setValue("candidates_out", "", "Optional output file with feature candidates.", output_file_tags); - defaults_.setValue("debug", 0, "Debug level for feature detection.", ListUtils::create("advanced")); + defaults_.setValue("debug", 0, "Debug level for feature detection.", {"advanced"}); defaults_.setMinInt("debug", 0); defaults_.setValue("extract:batch_size", 5000, "Nr of peptides used in each batch of chromatogram extraction." @@ -85,14 +85,14 @@ namespace OpenMS "extract:isotope_pmin", 0.0, "Minimum probability for an isotope to be included in the assay for a peptide. If set, this parameter takes precedence over 'extract:n_isotopes'.", - ListUtils::create("advanced")); + {"advanced"}); defaults_.setMinFloat("extract:isotope_pmin", 0.0); defaults_.setMaxFloat("extract:isotope_pmin", 1.0); defaults_.setValue( "extract:rt_quantile", 0.95, "Quantile of the RT deviations between aligned internal and external IDs to use for scaling the RT extraction window", - ListUtils::create("advanced")); + {"advanced"}); defaults_.setMinFloat("extract:rt_quantile", 0.0); defaults_.setMaxFloat("extract:rt_quantile", 1.0); @@ -100,7 +100,7 @@ namespace OpenMS "extract:rt_window", 0.0, "RT window size (in sec.) for chromatogram extraction. If set, this parameter takes precedence over 'extract:rt_quantile'.", - ListUtils::create("advanced")); + {"advanced"}); defaults_.setMinFloat("extract:rt_window", 0.0); defaults_.setSectionDescription("extract", "Parameters for ion chromatogram extraction"); @@ -111,14 +111,14 @@ namespace OpenMS "detect:min_peak_width", 0.2, "Minimum elution peak width. Absolute value in seconds if 1 or greater, else relative to 'peak_width'.", - ListUtils::create("advanced")); + {"advanced"}); defaults_.setMinFloat("detect:min_peak_width", 0.0); defaults_.setValue( "detect:signal_to_noise", 0.8, "Signal-to-noise threshold for OpenSWATH feature detection", - ListUtils::create("advanced")); + {"advanced"}); defaults_.setMinFloat("detect:signal_to_noise", 0.1); defaults_.setValue("detect:mapping_tolerance", 0.0, "RT tolerance (plus/minus) for mapping peptide IDs to features. Absolute value in seconds if 1 or greater, else relative to the RT span of the feature."); defaults_.setMinFloat("detect:mapping_tolerance", 0.0); @@ -129,13 +129,13 @@ namespace OpenMS defaults_.setValue("svm:samples", 0, "Number of observations to use for training ('0' for all)"); defaults_.setMinInt("svm:samples", 0); defaults_.setValue("svm:no_selection", "false", "By default, roughly the same number of positive and negative observations, with the same intensity distribution, are selected for training. This aims to reduce biases, but also reduces the amount of training data. Set this flag to skip this procedure and consider all available observations (subject to 'svm:samples')."); - defaults_.setValidStrings("svm:no_selection", ListUtils::create("true,false")); + defaults_.setValidStrings("svm:no_selection", {"true","false"}); defaults_.setValue("svm:xval_out", "", "Output file: SVM cross-validation (parameter optimization) results", output_file_tags); - defaults_.setValidStrings("svm:xval_out", ListUtils::create("csv")); + defaults_.setValidStrings("svm:xval_out", {"csv"}); defaults_.insert("svm:", SimpleSVM().getParameters()); defaults_.setValue("quantify_decoys", "false", "Whether decoy peptides should be quantified (true) or skipped (false)."); - defaults_.setValidStrings("quantify_decoys", ListUtils::create("true,false")); + defaults_.setValidStrings("quantify_decoys", {"true","false"}); // available scores: initialPeakQuality,total_xic,peak_apices_sum,var_xcorr_coelution,var_xcorr_coelution_weighted,var_xcorr_shape,var_xcorr_shape_weighted,var_library_corr,var_library_rmsd,var_library_sangle,var_library_rootmeansquare,var_library_manhattan,var_library_dotprod,var_intensity_score,nr_peaks,sn_ratio,var_log_sn_score,var_elution_model_fit_score,xx_lda_prelim_score,var_isotope_correlation_score,var_isotope_overlap_score,var_massdev_score,var_massdev_score_weighted,var_bseries_score,var_yseries_score,var_dotprod_score,var_manhatt_score,main_var_xx_swath_prelim_score,xx_swath_prelim_score // exclude some redundant/uninformative scores: @@ -147,20 +147,20 @@ namespace OpenMS "svm:predictors", score_metavalues, "Names of OpenSWATH scores to use as predictors for the SVM (comma-separated list)", - ListUtils::create("advanced")); + {"advanced"}); defaults_.setValue( "svm:min_prob", 0.0, "Minimum probability of correctness, as predicted by the SVM, required to retain a feature candidate", - ListUtils::create("advanced")); + {"advanced"}); defaults_.setMinFloat("svm:min_prob", 0.0); defaults_.setMaxFloat("svm:min_prob", 1.0); defaults_.setSectionDescription("svm", "Parameters for scoring features using a support vector machine (SVM)"); // parameters for model fitting (via ElutionModelFitter): - StringList models = ListUtils::create("symmetric,asymmetric,none"); + std::vector models = {"symmetric","asymmetric","none"}; defaults_.setValue("model:type", models[0], "Type of elution model to fit to features"); defaults_.setValidStrings("model:type", models); defaults_.insert("model:", ElutionModelFitter().getParameters()); // copy parameters @@ -1274,18 +1274,18 @@ namespace OpenMS mapping_tolerance_ = param_.getValue("detect:mapping_tolerance"); - elution_model_ = param_.getValue("model:type"); + elution_model_ = param_.getValue("model:type").toString(); // SVM related parameters svm_min_prob_ = param_.getValue("svm:min_prob"); svm_predictor_names_ = ListUtils::create(param_.getValue("svm:predictors").toString()); - svm_xval_out_ = param_.getValue("svm:xval_out"); + svm_xval_out_ = param_.getValue("svm:xval_out").toString(); svm_quality_cutoff = param_.getValue("svm:min_prob"); svm_n_parts_ = param_.getValue("svm:xval"); svm_n_samples_ = param_.getValue("svm:samples"); // debug debug_level_ = param_.getValue("debug"); - candidates_out_ = param_.getValue("candidates_out"); + candidates_out_ = param_.getValue("candidates_out").toString(); // quantification of decoys quantify_decoys_ = param_.getValue("quantify_decoys").toBool(); @@ -1494,7 +1494,7 @@ namespace OpenMS svm.setParameters(svm_params); svm.setup(predictors, training_labels); if (!svm_xval_out_.empty()) svm.writeXvalResults(svm_xval_out_); - if ((debug_level_ > 0) && String(svm_params.getValue("kernel")) == "linear") + if ((debug_level_ > 0) && svm_params.getValue("kernel") == "linear") { std::map feature_weights; svm.getFeatureWeights(feature_weights); diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderMultiplexAlgorithm.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderMultiplexAlgorithm.cpp index 0abd84489a1..dfd5645bfcd 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderMultiplexAlgorithm.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderMultiplexAlgorithm.cpp @@ -78,7 +78,7 @@ namespace OpenMS // parameter section: algorithm defaults_.setValue("algorithm:labels", "[][Lys8,Arg10]", "Labels used for labelling the samples. If the sample is unlabelled (i.e. you want to detect only single peptide features) please leave this parameter empty. [...] specifies the labels for a single sample. For example\n\n[][Lys8,Arg10] ... SILAC\n[][Lys4,Arg6][Lys8,Arg10] ... triple-SILAC\n[Dimethyl0][Dimethyl6] ... Dimethyl\n[Dimethyl0][Dimethyl4][Dimethyl8] ... triple Dimethyl\n[ICPL0][ICPL4][ICPL6][ICPL10] ... ICPL"); defaults_.setValue("algorithm:charge", "1:4", "Range of charge states in the sample, i.e. min charge : max charge."); - defaults_.setValue("algorithm:isotopes_per_peptide", "3:6", "Range of isotopes per peptide in the sample. For example 3:6, if isotopic peptide patterns in the sample consist of either three, four, five or six isotopic peaks. ", ListUtils::create("advanced")); + defaults_.setValue("algorithm:isotopes_per_peptide", "3:6", "Range of isotopes per peptide in the sample. For example 3:6, if isotopic peptide patterns in the sample consist of either three, four, five or six isotopic peaks. ", {"advanced"}); defaults_.setValue("algorithm:rt_typical", 40.0, "Typical retention time [s] over which a characteristic peptide elutes. (This is not an upper bound. Peptides that elute for longer will be reported.)"); defaults_.setMinFloat("algorithm:rt_typical", 0.0); defaults_.setValue("algorithm:rt_band", 0.0, "The algorithm searches for characteristic isotopic peak patterns, spectrum by spectrum. For some low-intensity peptides, an important peak might be missing in one spectrum but be present in one of the neighbouring ones. The algorithm takes a bundle of neighbouring spectra with width rt_band into account. For example with rt_band = 0, all characteristic isotopic peaks have to be present in one and the same spectrum. As rt_band increases, the sensitivity of the algorithm but also the likelihood of false detections increases."); @@ -88,7 +88,7 @@ namespace OpenMS defaults_.setValue("algorithm:mz_tolerance", 6.0, "m/z tolerance for search of peak patterns."); defaults_.setMinFloat("algorithm:mz_tolerance", 0.0); defaults_.setValue("algorithm:mz_unit", "ppm", "Unit of the 'mz_tolerance' parameter."); - defaults_.setValidStrings("algorithm:mz_unit", ListUtils::create("Da,ppm")); + defaults_.setValidStrings("algorithm:mz_unit", {"Da","ppm"}); defaults_.setValue("algorithm:intensity_cutoff", 1000.0, "Lower bound for the intensity of isotopic peaks."); defaults_.setMinFloat("algorithm:intensity_cutoff", 0.0); defaults_.setValue("algorithm:peptide_similarity", 0.5, "Two peptides in a multiplet are expected to have the same isotopic pattern. This parameter is a lower bound on their similarity."); @@ -97,22 +97,22 @@ namespace OpenMS defaults_.setValue("algorithm:averagine_similarity", 0.4, "The isotopic pattern of a peptide should resemble the averagine model at this m/z position. This parameter is a lower bound on similarity between measured isotopic pattern and the averagine model."); defaults_.setMinFloat("algorithm:averagine_similarity", -1.0); defaults_.setMaxFloat("algorithm:averagine_similarity", 1.0); - defaults_.setValue("algorithm:averagine_similarity_scaling", 0.95, "Let x denote this scaling factor, and p the averagine similarity parameter. For the detection of single peptides, the averagine parameter p is replaced by p' = p + x(1-p), i.e. x = 0 -> p' = p and x = 1 -> p' = 1. (For knock_out = true, peptide doublets and singlets are detected simultaneously. For singlets, the peptide similarity filter is irreleavant. In order to compensate for this 'missing filter', the averagine parameter p is replaced by the more restrictive p' when searching for singlets.)", ListUtils::create("advanced")); + defaults_.setValue("algorithm:averagine_similarity_scaling", 0.95, "Let x denote this scaling factor, and p the averagine similarity parameter. For the detection of single peptides, the averagine parameter p is replaced by p' = p + x(1-p), i.e. x = 0 -> p' = p and x = 1 -> p' = 1. (For knock_out = true, peptide doublets and singlets are detected simultaneously. For singlets, the peptide similarity filter is irreleavant. In order to compensate for this 'missing filter', the averagine parameter p is replaced by the more restrictive p' when searching for singlets.)", {"advanced"}); defaults_.setMinFloat("algorithm:averagine_similarity_scaling", 0.0); defaults_.setMaxFloat("algorithm:averagine_similarity_scaling", 1.0); defaults_.setValue("algorithm:missed_cleavages", 0, "Maximum number of missed cleavages due to incomplete digestion. (Only relevant if enzymatic cutting site coincides with labelling site. For example, Arg/Lys in the case of trypsin digestion and SILAC labelling.)"); defaults_.setMinInt("algorithm:missed_cleavages", 0); - defaults_.setValue("algorithm:spectrum_type", "automatic", "Type of MS1 spectra in input mzML file. 'automatic' determines the spectrum type directly from the input mzML file.", ListUtils::create("advanced")); - defaults_.setValidStrings("algorithm:spectrum_type", ListUtils::create("profile,centroid,automatic")); - defaults_.setValue("algorithm:averagine_type","peptide","The type of averagine to use, currently RNA, DNA or peptide", ListUtils::create("advanced")); - defaults_.setValidStrings("algorithm:averagine_type", ListUtils::create("peptide,RNA,DNA")); - defaults_.setValue("algorithm:knock_out", "false", "Is it likely that knock-outs are present? (Supported for doublex, triplex and quadruplex experiments only.)", ListUtils::create("advanced")); - defaults_.setValidStrings("algorithm:knock_out", ListUtils::create("true,false")); + defaults_.setValue("algorithm:spectrum_type", "automatic", "Type of MS1 spectra in input mzML file. 'automatic' determines the spectrum type directly from the input mzML file.", {"advanced"}); + defaults_.setValidStrings("algorithm:spectrum_type", {"profile","centroid","automatic"}); + defaults_.setValue("algorithm:averagine_type","peptide","The type of averagine to use, currently RNA, DNA or peptide", {"advanced"}); + defaults_.setValidStrings("algorithm:averagine_type", {"peptide","RNA","DNA"}); + defaults_.setValue("algorithm:knock_out", "false", "Is it likely that knock-outs are present? (Supported for doublex, triplex and quadruplex experiments only.)", {"advanced"}); + defaults_.setValidStrings("algorithm:knock_out", {"true","false"}); defaults_.setSectionDescription("algorithm", "algorithmic parameters"); // parameter section: labels - defaults_.setValue("labels:Arg6", 12.08, "description", ListUtils::create("advanced")); + defaults_.setValue("labels:Arg6", 12.08, "description", {"advanced"}); defaults_.setSectionDescription("labels", "mass shifts for all possible labels"); @@ -123,14 +123,14 @@ namespace OpenMS String label_name = "labels:"; label_name += it->name; - defaults_.setValue(label_name, it->value, it->description, ListUtils::create("advanced")); + defaults_.setValue(label_name, it->value, it->description, {"advanced"}); defaults_.setMinFloat(label_name, 0.0); label_mass_shift_.insert(make_pair(it->name, it->value)); } // parameter section: algorithm, get selected charge range - String charge_string = defaults_.getValue("algorithm:charge"); + String charge_string = defaults_.getValue("algorithm:charge").toString(); charge_min_ = charge_string.prefix(':').toInt(); charge_max_ = charge_string.suffix(':').toInt(); if (charge_min_ > charge_max_) @@ -139,7 +139,7 @@ namespace OpenMS } // parameter section: algorithm, get isotopes per peptide range - String isotopes_per_peptide_string = defaults_.getValue("algorithm:isotopes_per_peptide"); + String isotopes_per_peptide_string = defaults_.getValue("algorithm:isotopes_per_peptide").toString(); isotopes_per_peptide_min_ = isotopes_per_peptide_string.prefix(':').toInt(); isotopes_per_peptide_max_ = isotopes_per_peptide_string.suffix(':').toInt(); if (isotopes_per_peptide_min_ > isotopes_per_peptide_max_) @@ -899,7 +899,7 @@ namespace OpenMS void FeatureFinderMultiplexAlgorithm::run(MSExperiment& exp, bool progress) { // parameter section: algorithm, get selected charge range - String charge_string = param_.getValue("algorithm:charge"); + String charge_string = param_.getValue("algorithm:charge").toString(); charge_min_ = charge_string.prefix(':').toInt(); charge_max_ = charge_string.suffix(':').toInt(); if (charge_min_ > charge_max_) @@ -908,7 +908,7 @@ namespace OpenMS } // parameter section: algorithm, get isotopes per peptide range - String isotopes_per_peptide_string = param_.getValue("algorithm:isotopes_per_peptide"); + String isotopes_per_peptide_string = param_.getValue("algorithm:isotopes_per_peptide").toString(); isotopes_per_peptide_min_ = isotopes_per_peptide_string.prefix(':').toInt(); isotopes_per_peptide_max_ = isotopes_per_peptide_string.suffix(':').toInt(); if (isotopes_per_peptide_min_ > isotopes_per_peptide_max_) @@ -999,7 +999,7 @@ namespace OpenMS /** * generate peak patterns for subsequent filtering step */ - MultiplexDeltaMassesGenerator generator = MultiplexDeltaMassesGenerator(param_.getValue("algorithm:labels"), param_.getValue("algorithm:missed_cleavages"), label_mass_shift_); + MultiplexDeltaMassesGenerator generator = MultiplexDeltaMassesGenerator(param_.getValue("algorithm:labels").toString(), param_.getValue("algorithm:missed_cleavages"), label_mass_shift_); if (param_.getValue("algorithm:knock_out") == "true") { generator.generateKnockoutDeltaMasses(); @@ -1035,7 +1035,7 @@ namespace OpenMS /** * filter for peak patterns */ - MultiplexFilteringCentroided filtering(exp_centroid_, patterns, isotopes_per_peptide_min_, isotopes_per_peptide_max_, param_.getValue("algorithm:intensity_cutoff"), param_.getValue("algorithm:rt_band"), param_.getValue("algorithm:mz_tolerance"), (param_.getValue("algorithm:mz_unit") == "ppm"), param_.getValue("algorithm:peptide_similarity"), param_.getValue("algorithm:averagine_similarity"), averagine_similarity_scaling, param_.getValue("algorithm:averagine_type")); + MultiplexFilteringCentroided filtering(exp_centroid_, patterns, isotopes_per_peptide_min_, isotopes_per_peptide_max_, param_.getValue("algorithm:intensity_cutoff"), param_.getValue("algorithm:rt_band"), param_.getValue("algorithm:mz_tolerance"), (param_.getValue("algorithm:mz_unit") == "ppm"), param_.getValue("algorithm:peptide_similarity"), param_.getValue("algorithm:averagine_similarity"), averagine_similarity_scaling, param_.getValue("algorithm:averagine_type").toString()); filtering.setLogType(getLogType()); std::vector filter_results = filtering.filter(); @@ -1059,7 +1059,7 @@ namespace OpenMS /** * filter for peak patterns */ - MultiplexFilteringProfile filtering(exp_profile_, exp_centroid_, boundaries_exp_s, patterns, isotopes_per_peptide_min_, isotopes_per_peptide_max_, param_.getValue("algorithm:intensity_cutoff"), param_.getValue("algorithm:rt_band"), param_.getValue("algorithm:mz_tolerance"), (param_.getValue("algorithm:mz_unit") == "ppm"), param_.getValue("algorithm:peptide_similarity"), param_.getValue("algorithm:averagine_similarity"), averagine_similarity_scaling, param_.getValue("algorithm:averagine_type")); + MultiplexFilteringProfile filtering(exp_profile_, exp_centroid_, boundaries_exp_s, patterns, isotopes_per_peptide_min_, isotopes_per_peptide_max_, param_.getValue("algorithm:intensity_cutoff"), param_.getValue("algorithm:rt_band"), param_.getValue("algorithm:mz_tolerance"), (param_.getValue("algorithm:mz_unit") == "ppm"), param_.getValue("algorithm:peptide_similarity"), param_.getValue("algorithm:averagine_similarity"), averagine_similarity_scaling, param_.getValue("algorithm:averagine_type").toString()); filtering.setLogType(getLogType()); std::vector filter_results = filtering.filter(); exp_blacklist_ = filtering.getBlacklist(); @@ -1097,7 +1097,7 @@ namespace OpenMS std::vector > samples_labels; std::vector temp_samples; - String labels(param_.getValue("algorithm:labels")); + String labels(param_.getValue("algorithm:labels").toString()); boost::replace_all(labels, "[]", "no_label"); boost::replace_all(labels, "()", "no_label"); boost::replace_all(labels, "{}", "no_label"); diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/Fitter1D.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/Fitter1D.cpp index b163ec61cec..6c724618171 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/Fitter1D.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/Fitter1D.cpp @@ -48,10 +48,10 @@ namespace OpenMS Fitter1D::Fitter1D() : DefaultParamHandler("Fitter1D") { - defaults_.setValue("interpolation_step", 0.2, "Sampling rate for the interpolation of the model function.", ListUtils::create("advanced")); - defaults_.setValue("statistics:mean", 1.0, "Centroid position of the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:variance", 1.0, "The variance of the model.", ListUtils::create("advanced")); - defaults_.setValue("tolerance_stdev_bounding_box", 3.0, "Bounding box has range [minimim of data, maximum of data] enlarged by tolerance_stdev_bounding_box times the standard deviation of the data.", ListUtils::create("advanced")); + defaults_.setValue("interpolation_step", 0.2, "Sampling rate for the interpolation of the model function.", {"advanced"}); + defaults_.setValue("statistics:mean", 1.0, "Centroid position of the model.", {"advanced"}); + defaults_.setValue("statistics:variance", 1.0, "The variance of the model.", {"advanced"}); + defaults_.setValue("tolerance_stdev_bounding_box", 3.0, "Bounding box has range [minimim of data, maximum of data] enlarged by tolerance_stdev_bounding_box times the standard deviation of the data.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/GaussFitter1D.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/GaussFitter1D.cpp index 58a785a10c4..d2b30ceb780 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/GaussFitter1D.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/GaussFitter1D.cpp @@ -43,8 +43,8 @@ namespace OpenMS { setName(getProductName()); - defaults_.setValue("statistics:variance", 1.0, "Variance of the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:mean", 1.0, "Mean value of the model.", ListUtils::create("advanced")); + defaults_.setValue("statistics:variance", 1.0, "Variance of the model.", {"advanced"}); + defaults_.setValue("statistics:mean", 1.0, "Mean value of the model.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/GaussModel.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/GaussModel.cpp index a00a12e2f8d..05fa72b75ff 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/GaussModel.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/GaussModel.cpp @@ -42,10 +42,10 @@ namespace OpenMS { setName(getProductName()); - defaults_.setValue("bounding_box:min", 0.0, "Lower end of bounding box enclosing the data used to fit the model.", ListUtils::create("advanced")); - defaults_.setValue("bounding_box:max", 1.0, "Upper end of bounding box enclosing the data used to fit the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:mean", 0.0, "Centroid position of the model (Gaussian).", ListUtils::create("advanced")); - defaults_.setValue("statistics:variance", 1.0, "The variance of the Gaussian.", ListUtils::create("advanced")); + defaults_.setValue("bounding_box:min", 0.0, "Lower end of bounding box enclosing the data used to fit the model.", {"advanced"}); + defaults_.setValue("bounding_box:max", 1.0, "Upper end of bounding box enclosing the data used to fit the model.", {"advanced"}); + defaults_.setValue("statistics:mean", 0.0, "Centroid position of the model (Gaussian).", {"advanced"}); + defaults_.setValue("statistics:variance", 1.0, "The variance of the Gaussian.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/IsotopeFitter1D.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/IsotopeFitter1D.cpp index 64ecbe4eda1..4c1396d8edc 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/IsotopeFitter1D.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/IsotopeFitter1D.cpp @@ -45,11 +45,11 @@ namespace OpenMS { setName(getProductName()); - defaults_.setValue("statistics:variance", 1.0, "Variance of the model.", ListUtils::create("advanced")); - defaults_.setValue("charge", 1, "Charge state of the model.", ListUtils::create("advanced")); - defaults_.setValue("isotope:stdev", 1.0, "Standard deviation of gaussian applied to the averagine isotopic pattern to simulate the inaccuracy of the mass spectrometer.", ListUtils::create("advanced")); - defaults_.setValue("isotope:maximum", 100, "Maximum isotopic rank to be considered.", ListUtils::create("advanced")); - defaults_.setValue("interpolation_step", 0.1, "Sampling rate for the interpolation of the model function.", ListUtils::create("advanced")); + defaults_.setValue("statistics:variance", 1.0, "Variance of the model.", {"advanced"}); + defaults_.setValue("charge", 1, "Charge state of the model.", {"advanced"}); + defaults_.setValue("isotope:stdev", 1.0, "Standard deviation of gaussian applied to the averagine isotopic pattern to simulate the inaccuracy of the mass spectrometer.", {"advanced"}); + defaults_.setValue("isotope:maximum", 100, "Maximum isotopic rank to be considered.", {"advanced"}); + defaults_.setValue("interpolation_step", 0.1, "Sampling rate for the interpolation of the model function.", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/IsotopeModel.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/IsotopeModel.cpp index 37c32a03011..f4540bc6a5d 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/IsotopeModel.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/IsotopeModel.cpp @@ -47,24 +47,24 @@ namespace OpenMS { setName(getProductName()); - defaults_.setValue("averagines:C", 0.04443989f, "Number of C atoms per Dalton of mass.", ListUtils::create("advanced")); - defaults_.setValue("averagines:H", 0.06981572f, "Number of H atoms per Dalton of mass.", ListUtils::create("advanced")); - defaults_.setValue("averagines:N", 0.01221773f, "Number of N atoms per Dalton of mass.", ListUtils::create("advanced")); - defaults_.setValue("averagines:O", 0.01329399f, "Number of O atoms per Dalton of mass.", ListUtils::create("advanced")); - defaults_.setValue("averagines:S", 0.00037525f, "Number of S atoms per Dalton of mass.", ListUtils::create("advanced")); - defaults_.setValue("isotope:trim_right_cutoff", 0.001, "Cutoff in averagine distribution, trailing isotopes below this relative intensity are not considered.", ListUtils::create("advanced")); - defaults_.setValue("isotope:maximum", 100, "Maximum isotopic rank to be considered.", ListUtils::create("advanced")); - defaults_.setValue("isotope:distance", 1.000495, "Distance between consecutive isotopic peaks.", ListUtils::create("advanced")); + defaults_.setValue("averagines:C", 0.04443989f, "Number of C atoms per Dalton of mass.", {"advanced"}); + defaults_.setValue("averagines:H", 0.06981572f, "Number of H atoms per Dalton of mass.", {"advanced"}); + defaults_.setValue("averagines:N", 0.01221773f, "Number of N atoms per Dalton of mass.", {"advanced"}); + defaults_.setValue("averagines:O", 0.01329399f, "Number of O atoms per Dalton of mass.", {"advanced"}); + defaults_.setValue("averagines:S", 0.00037525f, "Number of S atoms per Dalton of mass.", {"advanced"}); + defaults_.setValue("isotope:trim_right_cutoff", 0.001, "Cutoff in averagine distribution, trailing isotopes below this relative intensity are not considered.", {"advanced"}); + defaults_.setValue("isotope:maximum", 100, "Maximum isotopic rank to be considered.", {"advanced"}); + defaults_.setValue("isotope:distance", 1.000495, "Distance between consecutive isotopic peaks.", {"advanced"}); - defaults_.setValue("isotope:mode:mode", "Gaussian", "Peak Shape used around each isotope peak.", ListUtils::create("advanced")); - defaults_.setValidStrings("isotope:mode:mode", ListUtils::create("Gaussian,Lorentzian")); - defaults_.setValue("isotope:mode:LorentzFWHM", 0.3, "Full width of the Lorentzian (Cauchy) function applied to the averagine isotopic pattern to simulate the inaccuracy of the mass spectrometer.", ListUtils::create("advanced")); - defaults_.setValue("isotope:mode:GaussianSD", 0.1, "Standard deviation of Gaussian applied to the averagine isotopic pattern to simulate the inaccuracy of the mass spectrometer.", ListUtils::create("advanced")); + defaults_.setValue("isotope:mode:mode", "Gaussian", "Peak Shape used around each isotope peak.", {"advanced"}); + defaults_.setValidStrings("isotope:mode:mode", {"Gaussian","Lorentzian"}); + defaults_.setValue("isotope:mode:LorentzFWHM", 0.3, "Full width of the Lorentzian (Cauchy) function applied to the averagine isotopic pattern to simulate the inaccuracy of the mass spectrometer.", {"advanced"}); + defaults_.setValue("isotope:mode:GaussianSD", 0.1, "Standard deviation of Gaussian applied to the averagine isotopic pattern to simulate the inaccuracy of the mass spectrometer.", {"advanced"}); - defaults_.setValue("charge", 1, "Charge state of the model.", ListUtils::create("advanced")); - defaults_.setValue("statistics:mean", 0.0, "Centroid m/z (as opposed to monoisotopic m/z).", ListUtils::create("advanced")); + defaults_.setValue("charge", 1, "Charge state of the model.", {"advanced"}); + defaults_.setValue("statistics:mean", 0.0, "Centroid m/z (as opposed to monoisotopic m/z).", {"advanced"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/TraceFitter.cpp b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/TraceFitter.cpp index 351ef18c6e2..866773f09d6 100644 --- a/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/TraceFitter.cpp +++ b/src/openms/source/TRANSFORMATIONS/FEATUREFINDER/TraceFitter.cpp @@ -59,9 +59,9 @@ namespace OpenMS TraceFitter::TraceFitter() : DefaultParamHandler("TraceFitter") { - defaults_.setValue("max_iteration", 500, "Maximum number of iterations used by the Levenberg-Marquardt algorithm.", ListUtils::create("advanced")); - defaults_.setValue("weighted", "false", "Weight mass traces according to their theoretical intensities.", ListUtils::create("advanced")); - defaults_.setValidStrings("weighted", ListUtils::create("true,false")); + defaults_.setValue("max_iteration", 500, "Maximum number of iterations used by the Levenberg-Marquardt algorithm.", {"advanced"}); + defaults_.setValue("weighted", "false", "Weight mass traces according to their theoretical intensities.", {"advanced"}); + defaults_.setValidStrings("weighted", {"true","false"}); defaultsToParam_(); } diff --git a/src/openms/source/TRANSFORMATIONS/RAW2PEAK/OptimizePeakDeconvolution.cpp b/src/openms/source/TRANSFORMATIONS/RAW2PEAK/OptimizePeakDeconvolution.cpp index d154cd18bb2..130cbf2fffc 100644 --- a/src/openms/source/TRANSFORMATIONS/RAW2PEAK/OptimizePeakDeconvolution.cpp +++ b/src/openms/source/TRANSFORMATIONS/RAW2PEAK/OptimizePeakDeconvolution.cpp @@ -335,8 +335,8 @@ namespace OpenMS { defaults_.setValue("max_iteration", 10, "maximal number of iterations for the fitting step"); - defaults_.setValue("eps_abs", 1e-04, "if the absolute error gets smaller than this value the fitting is stopped", ListUtils::create("advanced")); - defaults_.setValue("eps_rel", 1e-04, "if the relative error gets smaller than this value the fitting is stopped", ListUtils::create("advanced")); + defaults_.setValue("eps_abs", 1e-04, "if the absolute error gets smaller than this value the fitting is stopped", {"advanced"}); + defaults_.setValue("eps_rel", 1e-04, "if the relative error gets smaller than this value the fitting is stopped", {"advanced"}); defaults_.setValue("penalties:left_width", 0.0, "penalty term for the fitting of the left width:" \ "If the left width gets too broad or negative during the fitting it can be penalized."); diff --git a/src/openms/source/TRANSFORMATIONS/RAW2PEAK/PeakPickerCWT.cpp b/src/openms/source/TRANSFORMATIONS/RAW2PEAK/PeakPickerCWT.cpp index e59f67c20c2..668272b4b63 100644 --- a/src/openms/source/TRANSFORMATIONS/RAW2PEAK/PeakPickerCWT.cpp +++ b/src/openms/source/TRANSFORMATIONS/RAW2PEAK/PeakPickerCWT.cpp @@ -62,102 +62,102 @@ namespace OpenMS { defaults_.setValue("signal_to_noise", 1.0, "Minimal signal to noise ratio for a peak to be picked."); defaults_.setMinFloat("signal_to_noise", 0.0); - defaults_.setValue("thresholds:peak_bound", 10.0, "Minimal peak intensity.", ListUtils::create("advanced")); + defaults_.setValue("thresholds:peak_bound", 10.0, "Minimal peak intensity.", {"advanced"}); defaults_.setMinFloat("thresholds:peak_bound", 0.0); - defaults_.setValue("thresholds:peak_bound_ms2_level", 10.0, "Minimal peak intensity for MS/MS peaks.", ListUtils::create("advanced")); + defaults_.setValue("thresholds:peak_bound_ms2_level", 10.0, "Minimal peak intensity for MS/MS peaks.", {"advanced"}); defaults_.setMinFloat("thresholds:peak_bound_ms2_level", 0.0); // if a peak picking parameter is missed in the param object the value should be substituted by a default value defaults_.setValue("centroid_percentage", 0.8, "Percentage of the maximum height that the raw data points must exceed to be taken into account for the calculation of the centroid. " \ - "If it is 1 the centroid position corresponds to the position of the highest intensity.", ListUtils::create("advanced")); + "If it is 1 the centroid position corresponds to the position of the highest intensity.", {"advanced"}); defaults_.setMinFloat("centroid_percentage", 0.0); defaults_.setMaxFloat("centroid_percentage", 1.0); defaults_.setValue("thresholds:correlation", 0.5, "minimal correlation of a peak and the raw signal. " \ - "If a peak has a lower correlation it is skipped.", ListUtils::create("advanced")); + "If a peak has a lower correlation it is skipped.", {"advanced"}); defaults_.setMinFloat("thresholds:correlation", 0.0); defaults_.setMaxFloat("thresholds:correlation", 1.0); defaults_.setValue("peak_width", 0.15, "Approximate fwhm of the peaks."); defaults_.setMinFloat("peak_width", 0.0); defaults_.setValue("estimate_peak_width", "false", "Flag if the average peak width shall be estimated. Attention: when this flag is set, the peak_width is ignored."); - std::vector valid_opts; + std::vector valid_opts; valid_opts.push_back("true"); valid_opts.push_back("false"); defaults_.setValidStrings("estimate_peak_width", valid_opts); - defaults_.setValue("fwhm_lower_bound_factor", 0.7, "Factor that calculates the minimal fwhm value from the peak_width. All peaks with width smaller than fwhm_bound_factor * peak_width are discarded.", ListUtils::create("advanced")); - defaults_.setValue("fwhm_upper_bound_factor", 20., "Factor that calculates the maximal fwhm value from the peak_width. All peaks with width greater than fwhm_upper_bound_factor * peak_width are discarded.", ListUtils::create("advanced")); + defaults_.setValue("fwhm_lower_bound_factor", 0.7, "Factor that calculates the minimal fwhm value from the peak_width. All peaks with width smaller than fwhm_bound_factor * peak_width are discarded.", {"advanced"}); + defaults_.setValue("fwhm_upper_bound_factor", 20., "Factor that calculates the maximal fwhm value from the peak_width. All peaks with width greater than fwhm_upper_bound_factor * peak_width are discarded.", {"advanced"}); defaults_.setMinFloat("fwhm_lower_bound_factor", 0.0); defaults_.setMinFloat("fwhm_upper_bound_factor", 0.0); - defaults_.setValue("wavelet_transform:spacing", 0.001, "Spacing of the CWT. Note that the accuracy of the picked peak's centroid position depends in the Raw data spacing, i.e., 50% of raw peak distance at most.", ListUtils::create("advanced")); + defaults_.setValue("wavelet_transform:spacing", 0.001, "Spacing of the CWT. Note that the accuracy of the picked peak's centroid position depends in the Raw data spacing, i.e., 50% of raw peak distance at most.", {"advanced"}); defaults_.setMinFloat("wavelet_transform:spacing", 0.0); - defaults_.setValue("thresholds:noise_level", 0.1, "noise level for the search of the peak endpoints.", ListUtils::create("advanced")); + defaults_.setValue("thresholds:noise_level", 0.1, "noise level for the search of the peak endpoints.", {"advanced"}); defaults_.setMinFloat("thresholds:noise_level", 0.0); - defaults_.setValue("thresholds:search_radius", 3, "search radius for the search of the maximum in the signal after a maximum in the cwt was found", ListUtils::create("advanced")); + defaults_.setValue("thresholds:search_radius", 3, "search radius for the search of the maximum in the signal after a maximum in the cwt was found", {"advanced"}); defaults_.setMinInt("thresholds:search_radius", 0); //Optimization parameters defaults_.setValue("optimization", "no", "If the peak parameters position, intensity and left/right width" \ - "shall be optimized set optimization to one_dimensional or two_dimensional.", ListUtils::create("advanced")); + "shall be optimized set optimization to one_dimensional or two_dimensional.", {"advanced"}); valid_opts.clear(); valid_opts.push_back("no"); valid_opts.push_back("one_dimensional"); valid_opts.push_back("two_dimensional"); defaults_.setValidStrings("optimization", valid_opts); defaults_.setValue("optimization:penalties:position", 0.0, "penalty term for the fitting of the position:" \ - "If it differs too much from the initial one it can be penalized ", ListUtils::create("advanced")); + "If it differs too much from the initial one it can be penalized ", {"advanced"}); defaults_.setMinFloat("optimization:penalties:position", 0.0); defaults_.setValue("optimization:penalties:left_width", 1.0, "penalty term for the fitting of the left width:" \ - "If the left width differs too much from the initial one during the fitting it can be penalized.", ListUtils::create("advanced")); + "If the left width differs too much from the initial one during the fitting it can be penalized.", {"advanced"}); defaults_.setMinFloat("optimization:penalties:left_width", 0.0); defaults_.setValue("optimization:penalties:right_width", 1.0, "penalty term for the fitting of the right width:" \ - "If the right width differs too much from the initial one during the fitting it can be penalized.", ListUtils::create("advanced")); + "If the right width differs too much from the initial one during the fitting it can be penalized.", {"advanced"}); defaults_.setMinFloat("optimization:penalties:right_width", 0.0); defaults_.setValue("optimization:penalties:height", 1.0, "penalty term for the fitting of the intensity (only used in 2D Optimization):" \ - "If it gets negative during the fitting it can be penalized.", ListUtils::create("advanced")); + "If it gets negative during the fitting it can be penalized.", {"advanced"}); defaults_.setMinFloat("optimization:penalties:height", 0.0); - defaults_.setValue("optimization:iterations", 400, "maximal number of iterations for the fitting step", ListUtils::create("advanced")); + defaults_.setValue("optimization:iterations", 400, "maximal number of iterations for the fitting step", {"advanced"}); defaults_.setMinInt("optimization:iterations", 1); // additional 2d optimization parameters - defaults_.setValue("optimization:2d:tolerance_mz", 2.2, "mz tolerance for cluster construction", ListUtils::create("advanced")); + defaults_.setValue("optimization:2d:tolerance_mz", 2.2, "mz tolerance for cluster construction", {"advanced"}); defaults_.setMinFloat("optimization:2d:tolerance_mz", 0.0); - defaults_.setValue("optimization:2d:max_peak_distance", 1.2, "maximal peak distance in mz in a cluster", ListUtils::create("advanced")); + defaults_.setValue("optimization:2d:max_peak_distance", 1.2, "maximal peak distance in mz in a cluster", {"advanced"}); defaults_.setMinFloat("optimization:2d:max_peak_distance", 0.0); // deconvolution parameters - defaults_.setValue("deconvolution:deconvolution", "false", "If you want heavily overlapping peaks to be separated set this value to \"true\"", ListUtils::create("advanced")); + defaults_.setValue("deconvolution:deconvolution", "false", "If you want heavily overlapping peaks to be separated set this value to \"true\"", {"advanced"}); valid_opts.clear(); valid_opts.push_back("true"); valid_opts.push_back("false"); defaults_.setValidStrings("deconvolution:deconvolution", valid_opts); - defaults_.setValue("deconvolution:asym_threshold", 0.3, "If the symmetry of a peak is smaller than asym_thresholds it is assumed that it consists of more than one peak and the deconvolution procedure is started.", ListUtils::create("advanced")); + defaults_.setValue("deconvolution:asym_threshold", 0.3, "If the symmetry of a peak is smaller than asym_thresholds it is assumed that it consists of more than one peak and the deconvolution procedure is started.", {"advanced"}); defaults_.setMinFloat("deconvolution:asym_threshold", 0.0); - defaults_.setValue("deconvolution:left_width", 2.0, "1/left_width is the initial value for the left width of the peaks found in the deconvolution step.", ListUtils::create("advanced")); + defaults_.setValue("deconvolution:left_width", 2.0, "1/left_width is the initial value for the left width of the peaks found in the deconvolution step.", {"advanced"}); defaults_.setMinFloat("deconvolution:left_width", 0.0); - defaults_.setValue("deconvolution:right_width", 2.0, "1/right_width is the initial value for the right width of the peaks found in the deconvolution step.", ListUtils::create("advanced")); + defaults_.setValue("deconvolution:right_width", 2.0, "1/right_width is the initial value for the right width of the peaks found in the deconvolution step.", {"advanced"}); defaults_.setMinFloat("deconvolution:right_width", 0.0); - defaults_.setValue("deconvolution:scaling", 0.12, "Initial scaling of the cwt used in the separation of heavily overlapping peaks. The initial value is used for charge 1, for higher charges it is adapted to scaling/charge.", ListUtils::create("advanced")); + defaults_.setValue("deconvolution:scaling", 0.12, "Initial scaling of the cwt used in the separation of heavily overlapping peaks. The initial value is used for charge 1, for higher charges it is adapted to scaling/charge.", {"advanced"}); defaults_.setMinFloat("deconvolution:scaling", 0.0); defaults_.setValue("deconvolution:fitting:penalties:position", 0.0, "penalty term for the fitting of the peak position:" \ "If the position changes more than 0.5Da during the fitting it can be penalized as well as " \ - "discrepancies of the peptide mass rule.", ListUtils::create("advanced")); + "discrepancies of the peptide mass rule.", {"advanced"}); defaults_.setMinFloat("deconvolution:fitting:penalties:position", 0.0); defaults_.setValue("deconvolution:fitting:penalties:height", 1.0, "penalty term for the fitting of the intensity:" \ - "If it gets negative during the fitting it can be penalized.", ListUtils::create("advanced")); + "If it gets negative during the fitting it can be penalized.", {"advanced"}); defaults_.setMinFloat("deconvolution:fitting:penalties:height", 0.0); defaults_.setValue("deconvolution:fitting:penalties:left_width", 0.0, "penalty term for the fitting of the left width:" \ - "If the left width gets too broad or negative during the fitting it can be penalized.", ListUtils::create("advanced")); + "If the left width gets too broad or negative during the fitting it can be penalized.", {"advanced"}); defaults_.setMinFloat("deconvolution:fitting:penalties:left_width", 0.0); defaults_.setValue("deconvolution:fitting:penalties:right_width", 0.0, "penalty term for the fitting of the right width:" \ - "If the right width gets too broad or negative during the fitting it can be penalized.", ListUtils::create("advanced")); + "If the right width gets too broad or negative during the fitting it can be penalized.", {"advanced"}); defaults_.setMinFloat("deconvolution:fitting:penalties:right_width", 0.0); - defaults_.setValue("deconvolution:fitting:fwhm_threshold", 0.7, "If the FWHM of a peak is higher than 'fwhm_thresholds' it is assumed that it consists of more than one peak and the deconvolution procedure is started.", ListUtils::create("advanced")); + defaults_.setValue("deconvolution:fitting:fwhm_threshold", 0.7, "If the FWHM of a peak is higher than 'fwhm_thresholds' it is assumed that it consists of more than one peak and the deconvolution procedure is started.", {"advanced"}); defaults_.setMinFloat("deconvolution:fitting:fwhm_threshold", 0.0); - defaults_.setValue("deconvolution:fitting:eps_abs", 1e-05f, "if the absolute error gets smaller than this value the fitting is stopped.", ListUtils::create("advanced")); + defaults_.setValue("deconvolution:fitting:eps_abs", 1e-05f, "if the absolute error gets smaller than this value the fitting is stopped.", {"advanced"}); defaults_.setMinFloat("deconvolution:fitting:eps_abs", 0.0); - defaults_.setValue("deconvolution:fitting:eps_rel", 1e-05f, "if the relative error gets smaller than this value the fitting is stopped.", ListUtils::create("advanced")); + defaults_.setValue("deconvolution:fitting:eps_rel", 1e-05f, "if the relative error gets smaller than this value the fitting is stopped.", {"advanced"}); defaults_.setMinFloat("deconvolution:fitting:eps_rel", 0.0); - defaults_.setValue("deconvolution:fitting:max_iteration", 10, "maximal number of iterations for the fitting step", ListUtils::create("advanced")); + defaults_.setValue("deconvolution:fitting:max_iteration", 10, "maximal number of iterations for the fitting step", {"advanced"}); defaults_.setMinInt("deconvolution:fitting:max_iteration", 1); //this->subsections_.push_back("SignalToNoiseEstimationParameter"); diff --git a/src/openms/source/TRANSFORMATIONS/RAW2PEAK/PeakPickerHiRes.cpp b/src/openms/source/TRANSFORMATIONS/RAW2PEAK/PeakPickerHiRes.cpp index 4176984ce0f..975f8b33b3e 100644 --- a/src/openms/source/TRANSFORMATIONS/RAW2PEAK/PeakPickerHiRes.cpp +++ b/src/openms/source/TRANSFORMATIONS/RAW2PEAK/PeakPickerHiRes.cpp @@ -54,22 +54,22 @@ namespace OpenMS defaults_.setValue("signal_to_noise", 0.0, "Minimal signal-to-noise ratio for a peak to be picked (0.0 disables SNT estimation!)"); defaults_.setMinFloat("signal_to_noise", 0.0); - defaults_.setValue("spacing_difference_gap", 4.0, "The extension of a peak is stopped if the spacing between two subsequent data points exceeds 'spacing_difference_gap * min_spacing'. 'min_spacing' is the smaller of the two spacings from the peak apex to its two neighboring points. '0' to disable the constraint. Not applicable to chromatograms.", ListUtils::create("advanced")); + defaults_.setValue("spacing_difference_gap", 4.0, "The extension of a peak is stopped if the spacing between two subsequent data points exceeds 'spacing_difference_gap * min_spacing'. 'min_spacing' is the smaller of the two spacings from the peak apex to its two neighboring points. '0' to disable the constraint. Not applicable to chromatograms.", {"advanced"}); defaults_.setMinFloat("spacing_difference_gap", 0.0); - defaults_.setValue("spacing_difference", 1.5, "Maximum allowed difference between points during peak extension, in multiples of the minimal difference between the peak apex and its two neighboring points. If this difference is exceeded a missing point is assumed (see parameter 'missing'). A higher value implies a less stringent peak definition, since individual signals within the peak are allowed to be further apart. '0' to disable the constraint. Not applicable to chromatograms.", ListUtils::create("advanced")); + defaults_.setValue("spacing_difference", 1.5, "Maximum allowed difference between points during peak extension, in multiples of the minimal difference between the peak apex and its two neighboring points. If this difference is exceeded a missing point is assumed (see parameter 'missing'). A higher value implies a less stringent peak definition, since individual signals within the peak are allowed to be further apart. '0' to disable the constraint. Not applicable to chromatograms.", {"advanced"}); defaults_.setMinFloat("spacing_difference", 0.0); - defaults_.setValue("missing", 1, "Maximum number of missing points allowed when extending a peak to the left or to the right. A missing data point occurs if the spacing between two subsequent data points exceeds 'spacing_difference * min_spacing'. 'min_spacing' is the smaller of the two spacings from the peak apex to its two neighboring points. Not applicable to chromatograms.", ListUtils::create("advanced")); + defaults_.setValue("missing", 1, "Maximum number of missing points allowed when extending a peak to the left or to the right. A missing data point occurs if the spacing between two subsequent data points exceeds 'spacing_difference * min_spacing'. 'min_spacing' is the smaller of the two spacings from the peak apex to its two neighboring points. Not applicable to chromatograms.", {"advanced"}); defaults_.setMinInt("missing", 0); defaults_.setValue("ms_levels", ListUtils::create(""), "List of MS levels for which the peak picking is applied. If empty, auto mode is enabled, all peaks which aren't picked yet will get picked. Other scans are copied to the output without changes."); defaults_.setMinInt("ms_levels", 1); defaults_.setValue("report_FWHM", "false", "Add metadata for FWHM (as floatDataArray named 'FWHM' or 'FWHM_ppm', depending on param 'report_FWHM_unit') for each picked peak."); - defaults_.setValidStrings("report_FWHM", ListUtils::create("true,false")); + defaults_.setValidStrings("report_FWHM", {"true","false"}); defaults_.setValue("report_FWHM_unit", "relative", "Unit of FWHM. Either absolute in the unit of input, e.g. 'm/z' for spectra, or relative as ppm (only sensible for spectra, not chromatograms)."); - defaults_.setValidStrings("report_FWHM_unit", ListUtils::create("relative,absolute")); + defaults_.setValidStrings("report_FWHM_unit", {"relative","absolute"}); // parameters for STN estimator defaults_.insert("SignalToNoise:", SignalToNoiseEstimatorMedian< MSSpectrum >().getDefaults()); diff --git a/src/openms/source/TRANSFORMATIONS/RAW2PEAK/TwoDOptimization.cpp b/src/openms/source/TRANSFORMATIONS/RAW2PEAK/TwoDOptimization.cpp index d6f191ee370..d8934e74957 100644 --- a/src/openms/source/TRANSFORMATIONS/RAW2PEAK/TwoDOptimization.cpp +++ b/src/openms/source/TRANSFORMATIONS/RAW2PEAK/TwoDOptimization.cpp @@ -52,8 +52,8 @@ namespace OpenMS "If the left width gets too broad or negative during the fitting it can be penalized."); defaults_.setValue("penalties:right_width", 0.0, "penalty term for the fitting of the right width:" \ "If the right width gets too broad or negative during the fitting it can be penalized."); - defaults_.setValue("2d:tolerance_mz", 2.2, "mz tolerance for cluster construction", ListUtils::create("advanced")); - defaults_.setValue("2d:max_peak_distance", 1.2, "maximal peak distance in mz in a cluster", ListUtils::create("advanced")); + defaults_.setValue("2d:tolerance_mz", 2.2, "mz tolerance for cluster construction", {"advanced"}); + defaults_.setValue("2d:max_peak_distance", 1.2, "maximal peak distance in mz in a cluster", {"advanced"}); defaults_.setValue("iterations", 10, "maximal number of iterations for the fitting step"); diff --git a/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/INIFileEditorWindow.h b/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/INIFileEditorWindow.h index 0213841d4b7..03b9e176284 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/INIFileEditorWindow.h +++ b/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/INIFileEditorWindow.h @@ -39,6 +39,7 @@ #include #include +#include #include #include diff --git a/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/TOPPASBase.h b/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/TOPPASBase.h index 847df7ee3ee..ff00d7d172c 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/TOPPASBase.h +++ b/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/TOPPASBase.h @@ -98,7 +98,7 @@ If the filename is empty, the application name + ".ini" is used as filename /// stores the preferences (used when this window is closed) void savePreferences(); /// loads the files and updates the splash screen - void loadFiles(const StringList& list, QSplashScreen* splash_screen); + void loadFiles(const std::vector& list, QSplashScreen* splash_screen); public slots: /// opens the file in a new window diff --git a/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/TOPPViewBase.h b/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/TOPPViewBase.h index 39e6fdb0193..fda9ca9e589 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/TOPPViewBase.h +++ b/src/openms_gui/include/OpenMS/VISUAL/APPLICATIONS/TOPPViewBase.h @@ -48,6 +48,7 @@ #include #include #include +#include //STL #include @@ -151,12 +152,25 @@ namespace OpenMS typedef ExperimentType::SpectrumType SpectrumType; //@} + /// Used for deciding whether new tool/util params should be generated or reused from TOPPView's ini file + enum class TOOL_SCAN + { + /** + TVToolDiscovery does not generate params for each tool/util unless they are absolutely needed and could not be + extracted from TOPPView's ini file. This may be useful for testing. + */ + SKIP_SCAN, + /// Only generate params for each tool/util if TOPPView's last ini file has an older version. (Default behaviour) + SCAN_IF_NEWER_VERSION, + /// Forces TVToolDiscovery to generate params and using them instead of the params in TOPPView's ini file + FORCE_SCAN + }; + ///Constructor - TOPPViewBase(QWidget* parent = nullptr); + explicit TOPPViewBase(TOOL_SCAN scan_mode = TOOL_SCAN::SCAN_IF_NEWER_VERSION, QWidget* parent = nullptr); ///Destructor ~TOPPViewBase() override; - enum class LOAD_RESULT { OK, @@ -426,6 +440,11 @@ protected slots: /// Log output window LogWindow* log_; + /// Determines TVToolDiscovery scans for tool/utils and generates new params. + TOOL_SCAN scan_mode_; + /// Scans for tools/utils and generates a param for each. + TVToolDiscovery tool_scanner_; + /** @name Toolbar */ //@{ @@ -521,6 +540,9 @@ protected slots: /// Depending on the preferences this is static or changes with the current window/layer. String current_path_; + /// Adds tool/util params to param_ object by querying them from TVToolDiscovery + void addToolParamsToIni(); + private: /// Suffix appended to caption of tabs when layer is shown in 3D static const String CAPTION_3D_SUFFIX_; diff --git a/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/SwathTabWidget.h b/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/SwathTabWidget.h index f29c1275ccb..f79a779b3fd 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/SwathTabWidget.h +++ b/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/SwathTabWidget.h @@ -39,6 +39,7 @@ #include #include +#include #include #include #include diff --git a/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/TOPPASToolConfigDialog.h b/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/TOPPASToolConfigDialog.h index 149d5acd83a..a0929302e58 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/TOPPASToolConfigDialog.h +++ b/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/TOPPASToolConfigDialog.h @@ -38,6 +38,7 @@ #include #include +#include class QComboBox; class QPushButton; diff --git a/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/TheoreticalSpectrumGenerationDialog.h b/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/TheoreticalSpectrumGenerationDialog.h index 503c5bd2a41..970de1e9a4e 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/TheoreticalSpectrumGenerationDialog.h +++ b/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/TheoreticalSpectrumGenerationDialog.h @@ -39,6 +39,7 @@ class QListWidgetItem; class QListWidget; #include +#include namespace Ui { diff --git a/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/ToolsDialog.h b/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/ToolsDialog.h index 22487f0f172..dd675c68a15 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/ToolsDialog.h +++ b/src/openms_gui/include/OpenMS/VISUAL/DIALOGS/ToolsDialog.h @@ -43,7 +43,6 @@ class QLabel; class QComboBox; class QPushButton; -class QRadioButton; class QString; #include @@ -76,12 +75,13 @@ namespace OpenMS @brief Constructor @param parent Qt parent widget + @param params Containing all TOPP tool/util params @param ini_file The file name of the temporary INI file created by this dialog @param default_dir The default directory for loading and storing INI files @param layer_type The type of data (determines the applicable tools) @param layer_name The name of the selected layer */ - ToolsDialog(QWidget * parent, String ini_file, String default_dir, LayerData::DataType layer_type, String layer_name); + ToolsDialog(QWidget * parent, const Param& params, String ini_file, String default_dir, LayerData::DataType layer_type, String layer_name); ///Destructor ~ToolsDialog() override; @@ -119,13 +119,13 @@ namespace OpenMS QString filename_; /// Mapping of file extension to layer type to determine the type of a tool std::map tool_map_; + /// Param object containing all TOPP tool/util params + Param params_; ///Disables the ok button and input/output comboboxes void disable_(); ///Enables the ok button and input/output comboboxes void enable_(); - /// Generates an .ini file for a given tool name and loads it into a Param object. - Param getParamFromIni_(const String& tool_name); /// Determine all types a tool is compatible with by mapping each file extensions in a tools param std::vector getTypesFromParam_(const Param& p) const; // Fill input_combo_ and output_combo_ box with the appropriate entries from the specified param object. diff --git a/src/openms_gui/include/OpenMS/VISUAL/LayerData.h b/src/openms_gui/include/OpenMS/VISUAL/LayerData.h index aaea8d74d49..057cfa7f774 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/LayerData.h +++ b/src/openms_gui/include/OpenMS/VISUAL/LayerData.h @@ -282,13 +282,13 @@ namespace OpenMS /// Returns a const reference to the annotations of the current spectrum (1D view) const Annotations1DContainer & getCurrentAnnotations() const { - return annotations_1d[current_spectrum_]; + return annotations_1d[current_spectrum_idx_]; } /// Returns a mutable reference to the annotations of the current spectrum (1D view) Annotations1DContainer & getCurrentAnnotations() { - return annotations_1d[current_spectrum_]; + return annotations_1d[current_spectrum_idx_]; } /// Returns a const reference to the annotations of the current spectrum (1D view) @@ -321,13 +321,13 @@ namespace OpenMS /// Get the index of the current spectrum (1D view) Size getCurrentSpectrumIndex() const { - return current_spectrum_; + return current_spectrum_idx_; } /// Set the index of the current spectrum (1D view) void setCurrentSpectrumIndex(Size index) { - current_spectrum_ = index; + current_spectrum_idx_ = index; updateCache_(); } @@ -507,7 +507,7 @@ namespace OpenMS OSWDataSharedPtrType chrom_annotation_; /// Index of the current spectrum - Size current_spectrum_; + Size current_spectrum_idx_; /// Current cached spectrum ExperimentType::SpectrumType cached_spectrum_; diff --git a/src/openms_gui/include/OpenMS/VISUAL/PlotCanvas.h b/src/openms_gui/include/OpenMS/VISUAL/PlotCanvas.h index d28f96e7d73..637ef676a73 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/PlotCanvas.h +++ b/src/openms_gui/include/OpenMS/VISUAL/PlotCanvas.h @@ -925,6 +925,8 @@ protected slots: @brief Intensity scaling factor for 'snap to maximum intensity mode'. In this mode the highest currently visible intensity is treated like the maximum overall intensity. + + One entry per layer. */ std::vector snap_factors_; diff --git a/src/openms_gui/include/OpenMS/VISUAL/SpectraTreeTab.h b/src/openms_gui/include/OpenMS/VISUAL/SpectraTreeTab.h index dd2178e4d46..901544ef173 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/SpectraTreeTab.h +++ b/src/openms_gui/include/OpenMS/VISUAL/SpectraTreeTab.h @@ -77,7 +77,8 @@ namespace OpenMS /// Return a copy of the currently selected spectrum/chrom (for drag'n'drop to new window) /// and store it either as Spectrum or Chromatogram in @p exp (all other data is cleared) /// If no spectrum/chrom is selected, false is returned and @p exp is empty - bool getSelectedScan(MSExperiment& exp) const; + /// @param current_type Either DT_PEAK or DT_CHROMATOGRAM, depending on what is currently shown + bool getSelectedScan(MSExperiment& exp, LayerData::DataType& current_type) const; signals: void spectrumSelected(int); diff --git a/src/openms_gui/include/OpenMS/VISUAL/TOPPASToolVertex.h b/src/openms_gui/include/OpenMS/VISUAL/TOPPASToolVertex.h index 37a56b236fc..70c2f3602bb 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/TOPPASToolVertex.h +++ b/src/openms_gui/include/OpenMS/VISUAL/TOPPASToolVertex.h @@ -39,6 +39,7 @@ #include #include +#include #include diff --git a/src/openms_gui/include/OpenMS/VISUAL/TVToolDiscovery.h b/src/openms_gui/include/OpenMS/VISUAL/TVToolDiscovery.h new file mode 100644 index 00000000000..e9f222a25be --- /dev/null +++ b/src/openms_gui/include/OpenMS/VISUAL/TVToolDiscovery.h @@ -0,0 +1,102 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: David Voigt $ +// $Authors: David Voigt $ +// -------------------------------------------------------------------------- + +#pragma once + +#include + +#include +#include +#include + +namespace OpenMS +{ + /** + @brief Scans for tools/utils and generates a param for each asynchronously. + + @details All tools and utils listed in the ToolHandler class are considered. + + @example + @code + TVToolDiscovery scanner; + scanner.loadParams(); + // Do something else before explicitly waiting for the threads to finish + ... + // Wait when convenient. Keeps the GUI responsive while waiting + scanner.waitForParams(); + // Access the params. If no special timing for waiting or loading is needed this function can be safely called directly. + scanner.getToolParams(); + @endcode + */ + class OPENMS_GUI_DLLAPI TVToolDiscovery + { + public: + TVToolDiscovery() {}; + + TVToolDiscovery(const TVToolDiscovery &) = delete; + + TVToolDiscovery &operator=(const TVToolDiscovery &) = delete; + + ~TVToolDiscovery() {}; + + /// Start creating params for each tool/util asynchronously + void loadParams(); + + /** + @brief Wait for all future params to finish evaluating. + @details + While waiting the GUI remains responsive. After waiting it is safe to access the params without further waiting. + */ + void waitForParams(); + + /** + @brief Returns a hash map containing a param for each tool/util. + @details + Note that it is possible that not all param futures have been finished (or loaded) yet if this function is called. + In that case, the function starts param parsing (loadParam()) and waits for completion (waitForParams()) + before returning the result. + */ + const std::map &getToolParams(); + + private: + /// Returns param for a given tool/util. This function is thread-safe + static Param getParamFromIni_(const std::string &tool_name); + + /// Contains a param future for each tool/util name + std::map> param_futures_; + + /// Contains a mapping of each tool/util name to its param. + std::map params_; + }; +} \ No newline at end of file diff --git a/src/openms_gui/include/OpenMS/VISUAL/sources.cmake b/src/openms_gui/include/OpenMS/VISUAL/sources.cmake index 5dcace50869..a6f8f9d2524 100644 --- a/src/openms_gui/include/OpenMS/VISUAL/sources.cmake +++ b/src/openms_gui/include/OpenMS/VISUAL/sources.cmake @@ -58,6 +58,7 @@ TVControllerBase.h TVDIATreeTabController.h TVIdentificationViewController.h TVSpectraViewController.h +TVToolDiscovery.h ) ### add path to the filenames diff --git a/src/openms_gui/source/VISUAL/ANNOTATION/Annotation1DPeakItem.cpp b/src/openms_gui/source/VISUAL/ANNOTATION/Annotation1DPeakItem.cpp index 4b5c5babf8d..02aed93039f 100644 --- a/src/openms_gui/source/VISUAL/ANNOTATION/Annotation1DPeakItem.cpp +++ b/src/openms_gui/source/VISUAL/ANNOTATION/Annotation1DPeakItem.cpp @@ -221,11 +221,11 @@ namespace OpenMS // some pretty printing QString text = text_; - if (!text.contains("<\\")) // don't process HTML strings again + if (!text.contains(R"(<\)")) // don't process HTML strings again { // extract ion index { - QRegExp reg_exp("[abcdwxyz](\\d+)"); + QRegExp reg_exp(R"([abcdwxyz](\d+))"); int match_pos = reg_exp.indexIn(text); if (match_pos == 0) @@ -239,7 +239,7 @@ namespace OpenMS } else // protein-protein XL specific ion names { - QRegExp reg_exp_xlms("(ci|xi)[$][abcxyz](\\d+)"); + QRegExp reg_exp_xlms(R"((ci|xi)[$][abcxyz](\d+))"); match_pos = reg_exp_xlms.indexIn(text); if ( (match_pos == 6) || (match_pos == 7)) { @@ -269,7 +269,7 @@ namespace OpenMS text.replace("C3O","C3O"); // charge format: +z - QRegExp charge_rx("[\\+|\\-](\\d+)$"); + QRegExp charge_rx(R"([\+|\-](\d+)$)"); int match_pos = charge_rx.indexIn(text); if (match_pos > 0) { @@ -279,7 +279,7 @@ namespace OpenMS } // charge format: z+ - charge_rx = QRegExp("(\\d+)[\\+|\\-]$"); + charge_rx = QRegExp(R"((\d+)[\+|\-]$)"); match_pos = charge_rx.indexIn(text); if (match_pos > 0) { @@ -288,10 +288,10 @@ namespace OpenMS + text[match_pos + charge_rx.cap(1).size()] + QString(""); // + or - } - text.replace(QRegExp("\\+\\+$"), "2+"); - text.replace(QRegExp("\\+$"), ""); - text.replace(QRegExp("\\-\\-$"), "2-"); - text.replace(QRegExp("\\-$"), ""); + text.replace(QRegExp(R"(\+\+$)"), "2+"); + text.replace(QRegExp(R"(\+$)"), ""); + text.replace(QRegExp(R"(\-\-$)"), "2-"); + text.replace(QRegExp(R"(\-$)"), ""); } diff --git a/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/INIFileEditor.cpp b/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/INIFileEditor.cpp index b7850ef849c..9919581887e 100644 --- a/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/INIFileEditor.cpp +++ b/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/INIFileEditor.cpp @@ -72,10 +72,8 @@ using namespace std; int main(int argc, const char** argv) { - Map option_lists; - Map options; + std::map options, flags, option_lists; options["-print"] = "print"; - Map flags; flags["--help"] = "help"; Param param; param.parseCommandLine(argc, argv, options, flags, option_lists); @@ -107,7 +105,7 @@ int main(int argc, const char** argv) ParamXMLFile paramFile; try { - paramFile.load(param.getValue("print"), data); + paramFile.load(param.getValue("print").toString(), data); for (Param::ParamIterator it = data.begin(); it != data.end(); ++it) { cout << it.getName() << " = " << it->value << endl; diff --git a/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/SwathWizard.cpp b/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/SwathWizard.cpp index 5f4ba012997..8b3863e8734 100644 --- a/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/SwathWizard.cpp +++ b/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/SwathWizard.cpp @@ -167,7 +167,7 @@ void print_usage(Logger::LogStream& stream = OpenMS_Log_info) int main(int argc, const char** argv) { // list of all the valid options - Map valid_options, valid_flags, option_lists; + std::map valid_options, valid_flags, option_lists; valid_flags["--help"] = "help"; valid_flags["--debug"] = "debug"; valid_options["-ini"] = "ini"; @@ -195,7 +195,7 @@ int main(int argc, const char** argv) // if packed as Mac OS X bundle it will get a -psn_.. parameter by default from the OS // if this is the only unknown option it will be ignored .. maybe this should be solved directly // in Param.h - if (!(param.getValue("unknown").toString().hasSubstring("-psn") && !param.getValue("unknown").toString().hasSubstring(", "))) + if (!(String(param.getValue("unknown").toString()).hasSubstring("-psn") && !String(param.getValue("unknown").toString()).hasSubstring(", "))) { OPENMS_LOG_ERROR << "Unknown option(s) '" << param.getValue("unknown").toString() << "' given. Aborting!" << endl; print_usage(OpenMS_Log_error); diff --git a/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/TOPPAS.cpp b/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/TOPPAS.cpp index 8eaabe7786e..55778a09d3b 100644 --- a/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/TOPPAS.cpp +++ b/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/TOPPAS.cpp @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,7 @@ void print_usage(Logger::LogStream& stream = OpenMS_Log_info) int main(int argc, const char** argv) { // list of all the valid options - Map valid_options, valid_flags, option_lists; + std::map valid_options, valid_flags, option_lists; valid_flags["--help"] = "help"; valid_flags["--debug"] = "debug"; valid_options["-ini"] = "ini"; @@ -145,7 +146,7 @@ int main(int argc, const char** argv) // if TOPPAS is packed as Mac OS X bundle it will get a -psn_.. parameter by default from the OS // if this is the only unknown option it will be ignored .. maybe this should be solved directly // in Param.h - if (!(param.getValue("unknown").toString().hasSubstring("-psn") && !param.getValue("unknown").toString().hasSubstring(", "))) + if (!(String(param.getValue("unknown").toString()).hasSubstring("-psn") && !String(param.getValue("unknown").toString()).hasSubstring(", "))) { OPENMS_LOG_ERROR << "Unknown option(s) '" << param.getValue("unknown").toString() << "' given. Aborting!" << endl; print_usage(OpenMS_Log_error); @@ -184,12 +185,12 @@ int main(int argc, const char** argv) if (param.exists("ini")) { - mw->loadPreferences((String)param.getValue("ini")); + mw->loadPreferences(param.getValue("ini").toString()); } if (param.exists("misc")) { - mw->loadFiles(param.getValue("misc"), &splash_screen); + mw->loadFiles(ListUtils::toStringList(param.getValue("misc")), &splash_screen); } else { diff --git a/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/TOPPView.cpp b/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/TOPPView.cpp index ea1e304e091..714669845e9 100644 --- a/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/TOPPView.cpp +++ b/src/openms_gui/source/VISUAL/APPLICATIONS/GUITOOLS/TOPPView.cpp @@ -84,32 +84,34 @@ const char* tool_name = "TOPPView"; void print_usage() { cerr << endl - << tool_name << " -- A viewer for mass spectrometry data." << endl - << endl - << "Usage:" << endl - << " " << tool_name << " [options] [files]" << endl - << endl - << "Options are:" << endl - << " --help Shows this help" << endl - << " -ini Sets the INI file (default: ~/.TOPPView.ini)" << endl - << endl - << "Hints:" << endl - << " - To open several files in one window put a '+' in between the files." << endl - << " - '@bw' after a map file displays the dots in a white to black gradient." << endl - << " - '@bg' after a map file displays the dots in a grey to black gradient." << endl - << " - '@b' after a map file displays the dots in black." << endl - << " - '@r' after a map file displays the dots in red." << endl - << " - '@g' after a map file displays the dots in green." << endl - << " - '@m' after a map file displays the dots in magenta." << endl - << " - Example: '" << tool_name << " 1.mzML + 2.mzML @bw + 3.mzML @bg'" << endl + << tool_name << " -- A viewer for mass spectrometry data." << "\n" + << "\n" + << "Usage:" << "\n" + << " " << tool_name << " [options] [files]" << "\n" + << "\n" + << "Options are:" << "\n" + << " --help Shows this help" << "\n" + << " -ini Sets the INI file (default: ~/.TOPPView.ini)" << "\n" + << " --force Forces scan for new tools/utils" << "\n" + << "\n" + << "Hints:" << "\n" + << " - To open several files in one window put a '+' in between the files." << "\n" + << " - '@bw' after a map file displays the dots in a white to black gradient." << "\n" + << " - '@bg' after a map file displays the dots in a grey to black gradient." << "\n" + << " - '@b' after a map file displays the dots in black." << "\n" + << " - '@r' after a map file displays the dots in red." << "\n" + << " - '@g' after a map file displays the dots in green." << "\n" + << " - '@m' after a map file displays the dots in magenta." << "\n" + << " - Example: '" << tool_name << " 1.mzML + 2.mzML @bw + 3.mzML @bg'" << "\n" << endl; } int main(int argc, const char** argv) { //list of all the valid options - Map valid_options, valid_flags, option_lists; + std::map valid_options, valid_flags, option_lists; valid_flags["--help"] = "help"; + valid_flags["--force"] = "force"; valid_options["-ini"] = "ini"; Param param; @@ -128,7 +130,7 @@ int main(int argc, const char** argv) // if TOPPView is packed as Mac OS X bundle it will get a -psn_.. parameter by default from the OS // if this is the only unknown option it will be ignored .. maybe this should be solved directly // in Param.h - if (!(param.getValue("unknown").toString().hasSubstring("-psn") && !param.getValue("unknown").toString().hasSubstring(", "))) + if (!(String(param.getValue("unknown").toString()).hasSubstring("-psn") && !String(param.getValue("unknown").toString()).hasSubstring(", "))) { cout << "Unknown option(s) '" << param.getValue("unknown").toString() << "' given. Aborting!" << endl; print_usage(); @@ -141,7 +143,8 @@ int main(int argc, const char** argv) QApplicationTOPP a(argc, const_cast(argv)); a.connect(&a, &QApplicationTOPP::lastWindowClosed, &a, &QApplicationTOPP::quit); - TOPPViewBase tb; + TOPPViewBase::TOOL_SCAN mode = param.exists("force")? TOPPViewBase::TOOL_SCAN::FORCE_SCAN : TOPPViewBase::TOOL_SCAN::SCAN_IF_NEWER_VERSION; + TOPPViewBase tb(mode); a.connect(&a, &QApplicationTOPP::fileOpen, &tb, &TOPPViewBase::openFile); tb.show(); @@ -160,13 +163,13 @@ int main(int argc, const char** argv) if (param.exists("ini")) { - tb.loadPreferences((String)param.getValue("ini")); + tb.loadPreferences(param.getValue("ini").toString()); } //load command line files if (param.exists("misc")) { - tb.loadFiles(param.getValue("misc"), &splash_screen); + tb.loadFiles(ListUtils::toStringList(param.getValue("misc")), &splash_screen); } // We are about to show the application. diff --git a/src/openms_gui/source/VISUAL/APPLICATIONS/TOPPASBase.cpp b/src/openms_gui/source/VISUAL/APPLICATIONS/TOPPASBase.cpp index 2ef319073bf..05e30a360a8 100644 --- a/src/openms_gui/source/VISUAL/APPLICATIONS/TOPPASBase.cpp +++ b/src/openms_gui/source/VISUAL/APPLICATIONS/TOPPASBase.cpp @@ -211,7 +211,7 @@ namespace OpenMS //general defaults_.setValue("preferences:default_path", ".", "Default path for loading and storing files."); defaults_.setValue("preferences:default_path_current", "true", "If the current path is preferred over the default path."); - defaults_.setValidStrings("preferences:default_path_current", ListUtils::create("true,false")); + defaults_.setValidStrings("preferences:default_path_current", {"true","false"}); defaults_.setValue("preferences:version", "none", "OpenMS version, used to check if the TOPPAS.ini is up-to-date"); subsections_.push_back("preferences:RecentFiles"); defaultsToParam_(); @@ -254,7 +254,7 @@ namespace OpenMS connect(desc_, SIGNAL(textChanged()), this, SLOT(descriptionUpdated_())); // set current path - current_path_ = param_.getValue("preferences:default_path"); + current_path_ = param_.getValue("preferences:default_path").toString(); // set & create temporary path -- make sure its a new subdirectory, as it will be deleted later QString new_tmp_dir = File::getUniqueName(false).toQString(); @@ -1189,7 +1189,7 @@ namespace OpenMS return; //reset - current_path_ = param_.getValue("preferences:default_path"); + current_path_ = param_.getValue("preferences:default_path").toString(); //update if the current layer has a path associated TODO //if (activeCanvas_() && activeCanvas_()->getLayerCount()!=0 && activeCanvas_()->getCurrentLayer().filename!="") diff --git a/src/openms_gui/source/VISUAL/APPLICATIONS/TOPPViewBase.cpp b/src/openms_gui/source/VISUAL/APPLICATIONS/TOPPViewBase.cpp index 28eec3721ed..06ee73be348 100644 --- a/src/openms_gui/source/VISUAL/APPLICATIONS/TOPPViewBase.cpp +++ b/src/openms_gui/source/VISUAL/APPLICATIONS/TOPPViewBase.cpp @@ -52,7 +52,6 @@ #include #include #include -#include #include #include #include @@ -72,18 +71,16 @@ #include #include #include -#include -#include #include #include +#include +#include #include #include -#include #include +#include #include #include -#include -#include #include #include #include @@ -91,35 +88,33 @@ #include #include #include +#include +#include //Qt -#include +#include +#include #include #include +#include #include #include +#include #include -#include #include #include #include -#include -#include #include -#include #include -#include #include -#include #include +#include #include #include #include -#include #include -#include #include using namespace std; @@ -131,16 +126,16 @@ namespace OpenMS const String TOPPViewBase::CAPTION_3D_SUFFIX_ = " (3D)"; - /// supported types which can be opened with File-->Open const FileTypes::FileTypeList supported_types({ FileTypes::MZML, FileTypes::MZXML, FileTypes::MZDATA, FileTypes::SQMASS, FileTypes::FEATUREXML, FileTypes::CONSENSUSXML, FileTypes::IDXML, FileTypes::DTA, FileTypes::DTA2D, FileTypes::MGF, FileTypes::MS2, FileTypes::MSP, FileTypes::BZ2, FileTypes::GZ }); - TOPPViewBase::TOPPViewBase(QWidget* parent) : + TOPPViewBase::TOPPViewBase(TOOL_SCAN scan_mode, QWidget* parent) : QMainWindow(parent), DefaultParamHandler("TOPPViewBase"), + scan_mode_(scan_mode), ws_(this), tab_bar_(this), recent_files_(), @@ -447,7 +442,7 @@ namespace OpenMS loadPreferences(); // set current path - current_path_ = param_.getValue("preferences:default_path"); + current_path_ = param_.getValue("preferences:default_path").toString(); // update the menu updateMenu(); @@ -468,20 +463,20 @@ namespace OpenMS { //general defaults_.setValue("preferences:default_map_view", "2d", "Default visualization mode for maps."); - defaults_.setValidStrings("preferences:default_map_view", ListUtils::create("2d,3d")); + defaults_.setValidStrings("preferences:default_map_view", {"2d","3d"}); defaults_.setValue("preferences:default_path", ".", "Default path for loading and storing files."); defaults_.setValue("preferences:default_path_current", "true", "If the current path is preferred over the default path."); - defaults_.setValidStrings("preferences:default_path_current", ListUtils::create("true,false")); + defaults_.setValidStrings("preferences:default_path_current", {"true","false"}); defaults_.setValue("preferences:intensity_cutoff", "off", "Low intensity cutoff for maps."); - defaults_.setValidStrings("preferences:intensity_cutoff", ListUtils::create("on,off")); + defaults_.setValidStrings("preferences:intensity_cutoff", {"on","off"}); defaults_.setValue("preferences:on_file_change", "ask", "What action to take, when a data file changes. Do nothing, update automatically or ask the user."); - defaults_.setValidStrings("preferences:on_file_change", ListUtils::create("none,ask,update automatically")); + defaults_.setValidStrings("preferences:on_file_change", {"none","ask","update automatically"}); defaults_.setValue("preferences:topp_cleanup", "true", "If the temporary files for calling of TOPP tools should be removed after the call."); - defaults_.setValidStrings("preferences:topp_cleanup", ListUtils::create("true,false")); + defaults_.setValidStrings("preferences:topp_cleanup", {"true","false"}); defaults_.setValue("preferences:use_cached_ms2", "false", "If possible, only load MS1 spectra into memory and keep MS2 spectra on disk (using indexed mzML)."); - defaults_.setValidStrings("preferences:use_cached_ms2", ListUtils::create("true,false")); + defaults_.setValidStrings("preferences:use_cached_ms2", {"true","false"}); defaults_.setValue("preferences:use_cached_ms1", "false", "If possible, do not load MS1 spectra into memory spectra into memory and keep MS2 spectra on disk (using indexed mzML)."); - defaults_.setValidStrings("preferences:use_cached_ms1", ListUtils::create("true,false")); + defaults_.setValidStrings("preferences:use_cached_ms1", {"true","false"}); // 1d view defaults_.insert("preferences:1d:", Plot1DCanvas(Param()).getDefaults()); defaults_.setSectionDescription("preferences:1d", "Settings for single spectrum view."); @@ -571,8 +566,8 @@ namespace OpenMS // lock the GUI - no interaction possible when loading... GUIHelpers::GUILock glock(this); - bool cache_ms2_on_disc = ((String)param_.getValue("preferences:use_cached_ms2") == "true"); - bool cache_ms1_on_disc = ((String)param_.getValue("preferences:use_cached_ms1") == "true"); + bool cache_ms2_on_disc = (param_.getValue("preferences:use_cached_ms2") == "true"); + bool cache_ms1_on_disc = (param_.getValue("preferences:use_cached_ms1") == "true"); try { @@ -697,7 +692,6 @@ namespace OpenMS if (file_type == FileTypes::MZML) { // Load index only and check success (is it indexed?) - MzMLFile f; Internal::IndexedMzMLHandler indexed_mzml_file_; indexed_mzml_file_.openFile(filename); if ( indexed_mzml_file_.getParsingSuccess() && cache_ms2_on_disc) @@ -739,16 +733,8 @@ namespace OpenMS if (cache_ms1_on_disc && peak_map_sptr->getNrSpectra() > 0) peak_map_sptr->getSpectrum(0) = on_disc_peaks->getSpectrum(0); } } - else if (file_type == FileTypes::MSP) - { - MSPGenericFile().load(abs_filename, *peak_map_sptr); - for (size_t i = 0; i != peak_map_sptr->size(); ++i) - { - if ((*peak_map_sptr)[i].getRT() < 0) (*peak_map_sptr)[i].setRT(i); // set RT to spectrum index - } - } - // Load all data into memory if e.g. no mzML file + // Load all data into memory if e.g. other file type than mzML if (!parsing_success) { fh.loadExperiment(abs_filename, *peak_map_sptr, file_type, ProgressLogger::GUI); @@ -848,9 +834,9 @@ namespace OpenMS Size spectrum_id) { // initialize flags with defaults from the parameters - bool maps_as_2d = ((String)param_.getValue("preferences:default_map_view") == "2d"); + bool maps_as_2d = (param_.getValue("preferences:default_map_view") == "2d"); bool maps_as_1d = false; - bool use_intensity_cutoff = ((String)param_.getValue("preferences:intensity_cutoff") == "on"); + bool use_intensity_cutoff = (param_.getValue("preferences:intensity_cutoff") == "on"); bool is_dia_data = false; // feature, consensus feature and identifications can be merged @@ -1582,6 +1568,8 @@ namespace OpenMS // compose default ini file path String default_ini_file = String(QDir::homePath()) + "/.TOPPView.ini"; + bool tool_params_added = false; + if (filename == "") { filename = default_ini_file; } // load preferences, if file exists @@ -1597,14 +1585,13 @@ namespace OpenMS { error = true; } - //apply preferences if they are of the current TOPPView version if (!error && tmp.exists("preferences:version") && tmp.getValue("preferences:version").toString() == VersionInfo::getVersion()) { try { - setParameters(tmp); + setParameters(tmp.copy("preferences:")); } catch (Exception::InvalidParameter& /*e*/) { @@ -1615,13 +1602,18 @@ namespace OpenMS { error = true; } + // Load tool/util params + if (!error && scan_mode_ != TOOL_SCAN::FORCE_SCAN && tmp.hasSection("tool_params:")) + { + param_.insert("tool_params:", tmp.copy("tool_params:", true)); + tool_params_added = true; + } // set parameters to defaults when something is fishy with the parameters file if (error) { // reset parameters (they will be stored again when TOPPView quits) setParameters(Param()); - cerr << "The TOPPView preferences files '" << filename << "' was ignored. It is no longer compatible with this TOPPView version and will be replaced." << endl; } } @@ -1629,6 +1621,12 @@ namespace OpenMS { cerr << "Unable to load INI File: '" << filename << "'" << endl; } + // Scan for tools/utils if scan_mode is set to FORCE_SCAN or if the tool/util params could not be added for whatever reason + if (!tool_params_added && scan_mode_ != TOOL_SCAN::SKIP_SCAN) + { + tool_scanner_.loadParams(); + } + param_.setValue("PreferencesFile", filename); // set the recent files @@ -1640,14 +1638,21 @@ namespace OpenMS // replace recent files param_.removeAll("preferences:RecentFiles"); param_.insert("preferences:RecentFiles:", recent_files_.getAsParam()); - + // set version param_.setValue("preferences:version", VersionInfo::getVersion()); - - // save only the subsection that begins with "preferences:" + // Make sure TOPP tool/util params have been inserted + if (!param_.hasSection("tool_params:") && scan_mode_ != TOOL_SCAN::SKIP_SCAN) + { + addToolParamsToIni(); + } + // save only the subsection that begins with "preferences:" and all tool params ("tool_params:") try { - ParamXMLFile().store(string(param_.getValue("PreferencesFile")), param_.copy("preferences:")); + Param p; + p.insert("preferences:", param_.copy("preferences:", true)); + p.insert("tool_params:", param_.copy("tool_params:", true)); + ParamXMLFile().store(string(param_.getValue("PreferencesFile")), p); } catch (Exception::UnableToCreateFile& /*e*/) { @@ -1655,6 +1660,16 @@ namespace OpenMS } } + void TOPPViewBase::addToolParamsToIni() + { + tool_scanner_.waitForParams(); + param_.addSection("tool_params", ""); + for (const auto& pair : tool_scanner_.getToolParams()) + { + param_.insert("tool_params:", pair.second); + } + } + QStringList TOPPViewBase::chooseFilesDialog_(const String& path_overwrite) { // store active sub window @@ -1708,7 +1723,11 @@ namespace OpenMS log_->appendNewHeader(LogWindow::LogState::CRITICAL, "Cannot create temporary file", String("Cannot write to '") + topp_.file_name + "'_ini!"); return; } - ToolsDialog tools_dialog(this, topp_.file_name + "_ini", current_path_, layer.type, layer.getName()); + if (!param_.hasSection("tool_params:")) + { + addToolParamsToIni(); + } + ToolsDialog tools_dialog(this, param_.copy("tool_params:", true), topp_.file_name + "_ini", current_path_, layer.type, layer.getName()); if (tools_dialog.exec() == QDialog::Accepted) { @@ -2075,7 +2094,7 @@ namespace OpenMS ConsensusMapSharedPtrType c_dummy(new ConsensusMapType()); ODExperimentSharedPtrType od_dummy(new OnDiscMSExperiment()); vector p_dummy; - addData(f_dummy, c_dummy, p_dummy, new_exp_sptr, od_dummy, LayerData::DT_CHROMATOGRAM, false, true, true, "", seq_string + QString(" (theoretical)")); + addData(f_dummy, c_dummy, p_dummy, new_exp_sptr, od_dummy, LayerData::DT_PEAK, false, true, true, "", seq_string + " (theoretical)"); // ensure spectrum is drawn as sticks draw_group_1d_->button(Plot1DCanvas::DM_PEAKS)->setChecked(true); @@ -2600,14 +2619,14 @@ namespace OpenMS else if (spec_view != nullptr) { ExperimentSharedPtrType new_exp_sptr(new ExperimentType()); - if (spec_view->getSelectedScan(*new_exp_sptr)) + if (LayerData::DataType current_type; spec_view->getSelectedScan(*new_exp_sptr, current_type)) { ODExperimentSharedPtrType od_dummy(new OnDiscMSExperiment()); FeatureMapSharedPtrType f_dummy(new FeatureMapType()); ConsensusMapSharedPtrType c_dummy(new ConsensusMapType()); vector p_dummy; const LayerData& layer = getActiveCanvas()->getCurrentLayer(); - addData(f_dummy, c_dummy, p_dummy, new_exp_sptr, od_dummy, new_exp_sptr->getNrSpectra() > 0 ? LayerData::DT_PEAK : LayerData::DT_CHROMATOGRAM, false, false, true, layer.filename, layer.getName(), new_id); + addData(f_dummy, c_dummy, p_dummy, new_exp_sptr, od_dummy, current_type, false, false, true, layer.filename, layer.getName(), new_id); } } else if (source == nullptr) @@ -2639,7 +2658,7 @@ namespace OpenMS } //reset - current_path_ = param_.getValue("preferences:default_path"); + current_path_ = param_.getValue("preferences:default_path").toString(); //update if the current layer has a path associated if (getActiveCanvas() && getActiveCanvas()->getLayerCount() != 0 && getActiveCanvas()->getCurrentLayer().filename != "") @@ -2693,11 +2712,11 @@ namespace OpenMS Size layer_index = slp.second; bool user_wants_update = false; - if ((String)(param_.getValue("preferences:on_file_change")) == "update automatically") //automatically update + if (param_.getValue("preferences:on_file_change") == "update automatically") //automatically update { user_wants_update = true; } - else if ((String)(param_.getValue("preferences:on_file_change")) == "ask") //ask the user if the layer should be updated + else if (param_.getValue("preferences:on_file_change") == "ask") //ask the user if the layer should be updated { if (watcher_msgbox_ == true) // we already have a dialog for that opened... do not ask again { diff --git a/src/openms_gui/source/VISUAL/DIALOGS/LayerStatisticsDialog.cpp b/src/openms_gui/source/VISUAL/DIALOGS/LayerStatisticsDialog.cpp index 09950c53ab4..9c4a8b1d489 100644 --- a/src/openms_gui/source/VISUAL/DIALOGS/LayerStatisticsDialog.cpp +++ b/src/openms_gui/source/VISUAL/DIALOGS/LayerStatisticsDialog.cpp @@ -190,34 +190,32 @@ namespace OpenMS ui_->table_->setCellWidget(0, 4, button); connect(button, SIGNAL(clicked()), this, SLOT(showDistribution_())); - // add computed stats about meta infos in the FloatDataArrays of the spectra to the table - for (std::map::const_iterator it = meta_array_stats_.begin(); it != meta_array_stats_.end(); ++it) + for (const auto& [name, meta_stats_value] : meta_array_stats_) { ui_->table_->setRowCount(ui_->table_->rowCount() + 1); - String name = it->first; item = new QTableWidgetItem(); item->setText(name.toQString()); ui_->table_->setVerticalHeaderItem(ui_->table_->rowCount() - 1, item); item = new QTableWidgetItem(); - item->setText(QString::number(it->second.count)); + item->setText(QString::number(meta_stats_value.count)); ui_->table_->setItem(ui_->table_->rowCount() - 1, 0, item); item = new QTableWidgetItem(); - item->setText(QString::number(it->second.min, 'f', 2)); + item->setText(QString::number(meta_stats_value.min, 'f', 2)); ui_->table_->setItem(ui_->table_->rowCount() - 1, 1, item); item = new QTableWidgetItem(); - item->setText(QString::number(it->second.max, 'f', 2)); + item->setText(QString::number(meta_stats_value.max, 'f', 2)); ui_->table_->setItem(ui_->table_->rowCount() - 1, 2, item); item = new QTableWidgetItem(); - item->setText(QString::number(it->second.avg, 'f', 2)); + item->setText(QString::number(meta_stats_value.avg, 'f', 2)); ui_->table_->setItem(ui_->table_->rowCount() - 1, 3, item); - if (it->second.count >= 2 && it->second.min < it->second.max) + if (meta_stats_value.count >= 2 && meta_stats_value.min < meta_stats_value.max) { button = new QPushButton(name.toQString(), ui_->table_); ui_->table_->setCellWidget(ui_->table_->rowCount() - 1, 4, button); diff --git a/src/openms_gui/source/VISUAL/DIALOGS/SwathTabWidget.cpp b/src/openms_gui/source/VISUAL/DIALOGS/SwathTabWidget.cpp index 6c69241470d..ca2b00e5b54 100644 --- a/src/openms_gui/source/VISUAL/DIALOGS/SwathTabWidget.cpp +++ b/src/openms_gui/source/VISUAL/DIALOGS/SwathTabWidget.cpp @@ -261,8 +261,8 @@ namespace OpenMS Param tmp; // grab the files - tmp.setValue("tr", ui->input_tr->getFilename()); - tmp.setValue("tr_irt", ui->input_iRT->getFilename()); + tmp.setValue("tr", ui->input_tr->getFilename().toStdString()); + tmp.setValue("tr_irt", ui->input_iRT->getFilename().toStdString()); // do not set 'in' because it allows for one file only, while we have more and need to iterate manually String swath_windows = ui->input_swath_windows->getFilename(); if (!swath_windows.empty()) tmp.setValue("swath_windows_file", swath_windows); diff --git a/src/openms_gui/source/VISUAL/DIALOGS/TOPPViewOpenDialog.cpp b/src/openms_gui/source/VISUAL/DIALOGS/TOPPViewOpenDialog.cpp index 166cdc44561..36d92919fff 100644 --- a/src/openms_gui/source/VISUAL/DIALOGS/TOPPViewOpenDialog.cpp +++ b/src/openms_gui/source/VISUAL/DIALOGS/TOPPViewOpenDialog.cpp @@ -38,6 +38,7 @@ #include #include +#include // QT includes diff --git a/src/openms_gui/source/VISUAL/DIALOGS/TOPPViewPrefDialog.cpp b/src/openms_gui/source/VISUAL/DIALOGS/TOPPViewPrefDialog.cpp index 94d1b04ac2c..8dd37d11e51 100644 --- a/src/openms_gui/source/VISUAL/DIALOGS/TOPPViewPrefDialog.cpp +++ b/src/openms_gui/source/VISUAL/DIALOGS/TOPPViewPrefDialog.cpp @@ -36,6 +36,8 @@ #include #include +#include +#include #include @@ -66,24 +68,24 @@ namespace OpenMS // Set dialog entries from current parameter object (default values) // default - ui_->default_path->setText(param_.getValue("preferences:default_path").toQString()); + ui_->default_path->setText(String(param_.getValue("preferences:default_path").toString()).toQString()); ui_->default_path_current->setChecked(param_.getValue("preferences:default_path_current").toBool()); ui_->use_cached_ms1->setChecked(param_.getValue("preferences:use_cached_ms1").toBool()); ui_->use_cached_ms2->setChecked(param_.getValue("preferences:use_cached_ms2").toBool()); - ui_->map_default->setCurrentIndex(ui_->map_default->findText(param_.getValue("preferences:default_map_view").toQString())); - ui_->map_cutoff->setCurrentIndex(ui_->map_cutoff->findText(param_.getValue("preferences:intensity_cutoff").toQString())); - ui_->on_file_change->setCurrentIndex(ui_->on_file_change->findText(param_.getValue("preferences:on_file_change").toQString())); + ui_->map_default->setCurrentIndex(ui_->map_default->findText(String(param_.getValue("preferences:default_map_view").toString()).toQString())); + ui_->map_cutoff->setCurrentIndex(ui_->map_cutoff->findText(String(param_.getValue("preferences:intensity_cutoff").toString()).toQString())); + ui_->on_file_change->setCurrentIndex(ui_->on_file_change->findText(String(param_.getValue("preferences:on_file_change").toString()).toQString())); // 1D view - ui_->color_1D->setColor(QColor(param_.getValue("preferences:1d:peak_color").toQString())); - ui_->selected_1D->setColor(QColor(param_.getValue("preferences:1d:highlighted_peak_color").toQString())); - ui_->icon_1D->setColor(QColor(param_.getValue("preferences:1d:icon_color").toQString())); + ui_->color_1D->setColor(QColor(String(param_.getValue("preferences:1d:peak_color").toString()).toQString())); + ui_->selected_1D->setColor(QColor(String(param_.getValue("preferences:1d:highlighted_peak_color").toString()).toQString())); + ui_->icon_1D->setColor(QColor(String(param_.getValue("preferences:1d:icon_color").toString()).toQString())); // 2D view ui_->peak_2D->gradient().fromString(param_.getValue("preferences:2d:dot:gradient")); - ui_->mapping_2D->setCurrentIndex(ui_->mapping_2D->findText(param_.getValue("preferences:2d:mapping_of_mz_to").toQString())); - ui_->feature_icon_2D->setCurrentIndex(ui_->feature_icon_2D->findText(param_.getValue("preferences:2d:dot:feature_icon").toQString())); + ui_->mapping_2D->setCurrentIndex(ui_->mapping_2D->findText(String(param_.getValue("preferences:2d:mapping_of_mz_to").toString()).toQString())); + ui_->feature_icon_2D->setCurrentIndex(ui_->feature_icon_2D->findText(String(param_.getValue("preferences:2d:dot:feature_icon").toString()).toQString())); ui_->feature_icon_size_2D->setValue((Int)param_.getValue("preferences:2d:dot:feature_icon_size")); // 3D view @@ -149,23 +151,23 @@ namespace OpenMS Param TOPPViewPrefDialog::getParam() const { Param p; - p.setValue("preferences:default_path", ui_->default_path->text()); - p.setValue("preferences:default_path_current", ui_->default_path_current->isChecked()); + p.setValue("preferences:default_path", ui_->default_path->text().toStdString()); + p.setValue("preferences:default_path_current", fromCheckState(ui_->default_path_current->checkState())); - p.setValue("preferences:use_cached_ms1", ui_->use_cached_ms1->isChecked()); - p.setValue("preferences:use_cached_ms2", ui_->use_cached_ms2->isChecked()); + p.setValue("preferences:use_cached_ms1", fromCheckState(ui_->use_cached_ms1->checkState())); + p.setValue("preferences:use_cached_ms2", fromCheckState(ui_->use_cached_ms2->checkState())); - p.setValue("preferences:default_map_view", ui_->map_default->currentText()); - p.setValue("preferences:intensity_cutoff", ui_->map_cutoff->currentText()); - p.setValue("preferences:on_file_change", ui_->on_file_change->currentText()); + p.setValue("preferences:default_map_view", ui_->map_default->currentText().toStdString()); + p.setValue("preferences:intensity_cutoff", ui_->map_cutoff->currentText().toStdString()); + p.setValue("preferences:on_file_change", ui_->on_file_change->currentText().toStdString()); - p.setValue("preferences:1d:peak_color", ui_->color_1D->getColor().name()); - p.setValue("preferences:1d:highlighted_peak_color", ui_->selected_1D->getColor().name()); - p.setValue("preferences:1d:icon_color", ui_->icon_1D->getColor().name()); + p.setValue("preferences:1d:peak_color", ui_->color_1D->getColor().name().toStdString()); + p.setValue("preferences:1d:highlighted_peak_color", ui_->selected_1D->getColor().name().toStdString()); + p.setValue("preferences:1d:icon_color", ui_->icon_1D->getColor().name().toStdString()); p.setValue("preferences:2d:dot:gradient", ui_->peak_2D->gradient().toString()); - p.setValue("preferences:2d:mapping_of_mz_to", ui_->mapping_2D->currentText()); - p.setValue("preferences:2d:dot:feature_icon", ui_->feature_icon_2D->currentText()); + p.setValue("preferences:2d:mapping_of_mz_to", ui_->mapping_2D->currentText().toStdString()); + p.setValue("preferences:2d:dot:feature_icon", ui_->feature_icon_2D->currentText().toStdString()); p.setValue("preferences:2d:dot:feature_icon_size", ui_->feature_icon_size_2D->value()); p.setValue("preferences:3d:dot:gradient", ui_->peak_3D->gradient().toString()); @@ -204,9 +206,18 @@ namespace OpenMS p.setValue("preferences:idview:add_isotopes", fromCheckState(ic_ions[0]->checkState()), "Show isotopes"); p.setValue("preferences:idview:add_abundant_immonium_ions", fromCheckState(ai_ions[0]->checkState()), "Show abundant immonium ions"); - if (param_.empty()) param_ = p; // if setParam() was not called before, param_ is empty and p is the only thing we have... - else param_.update(p, false); // update with new values from 'p' to avoid loosing additional parameters and the existing descriptions already present in param_ - + // if setParam() was not called before, param_ is empty and p is the only thing we have... + if (param_.empty()) + { + param_ = p; + } + // update with new values from 'p' to avoid loosing additional parameters and the existing descriptions already present in param_ + else if (!param_.update(p, true, true, true, true, OpenMS_Log_warn)) + { // fails if parameter types are incompatible, e.g. param_.getValue("checkbox") is STRING, but p.setValue("checkBox", 1), i.e. Int was stored. + // You should see 'Parameter 'preferences:use_cached_ms2' has changed value type!' or similar in the console + throw Exception::InvalidParameter(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Storing parameters failed. This is a bug! Please report it!"); + } + return param_; } diff --git a/src/openms_gui/source/VISUAL/DIALOGS/ToolsDialog.cpp b/src/openms_gui/source/VISUAL/DIALOGS/ToolsDialog.cpp index d929fffd8cb..aec34ba5fb4 100644 --- a/src/openms_gui/source/VISUAL/DIALOGS/ToolsDialog.cpp +++ b/src/openms_gui/source/VISUAL/DIALOGS/ToolsDialog.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include @@ -52,13 +51,10 @@ #include #include -#include -#include - -#include #include #include #include +#include using namespace std; @@ -67,6 +63,7 @@ namespace OpenMS ToolsDialog::ToolsDialog( QWidget* parent, + const Param& params, String ini_file, String default_dir, LayerData::DataType layer_type, @@ -74,7 +71,8 @@ namespace OpenMS ) : QDialog(parent), ini_file_(ini_file), - default_dir_(default_dir) + default_dir_(default_dir), + params_(params) { auto main_grid = new QGridLayout(this); @@ -96,17 +94,22 @@ namespace OpenMS {FileTypes::Type::CONSENSUSXML, LayerData::DataType::DT_CONSENSUS}, {FileTypes::Type::IDXML, LayerData::DataType::DT_IDENT} }; - // Get a map of all tools - const auto& tools = OpenMS::ToolHandler::getTOPPToolList(); - for (const auto& tool : tools) + const auto& tools = ToolHandler::getTOPPToolList(); + const auto& utils = ToolHandler::getUtilList(); + for (auto& pair : tools) { - const String& tool_name = tool.first; - Param p = getParamFromIni_(tool_name); - std::vector tool_types = getTypesFromParam_(p); - // Check if tool is compatible with the layer type + std::vector tool_types = getTypesFromParam_(params.copy(pair.first + ":")); if (std::find(tool_types.begin(), tool_types.end(), layer_type) != tool_types.end()) { - list << tool_name.toQString(); + list << pair.first.toQString(); + } + } + for (auto& pair : utils) + { + std::vector tool_types = getTypesFromParam_(params.copy(pair.first + ":")); + if (std::find(tool_types.begin(), tool_types.end(), layer_type) != tool_types.end()) + { + list << pair.first.toQString(); } } @@ -166,31 +169,6 @@ namespace OpenMS ToolsDialog::~ToolsDialog() { - - } - - Param ToolsDialog::getParamFromIni_(const String& tool_name) - { - QStringList args{ "-write_ini", ini_file_.toQString(), "-log", (ini_file_+".log").toQString() }; - QProcess qp; - String executable = File::findSiblingTOPPExecutable(tool_name); - qp.start(executable.toQString(), args); - const bool success = qp.waitForFinished(-1); // wait till job is finished - if (qp.error() == QProcess::FailedToStart || success == false || qp.exitStatus() != 0 || qp.exitCode() != 0) - { - QMessageBox::critical(this, "Error", (String("Could not execute '") + executable + "'!\n\nMake sure the TOPP tools are present in '" + File::getExecutablePath() + "', that you have permission to write to the temporary file path, and that there is space left in the temporary file path.").c_str()); - // TODO handle error - } - else if (!File::exists(ini_file_)) - { - QMessageBox::critical(this, "Error", (String("Could find requested INI file '") + ini_file_ + "'!").c_str()); - // TODO handle error - } - Param tool_param; - ParamXMLFile paramFile; - paramFile.load((ini_file_).c_str(), tool_param); - - return tool_param; } std::vector ToolsDialog::getTypesFromParam_(const Param& p) const @@ -276,9 +254,9 @@ namespace OpenMS editor_->clear(); arg_map_.clear(); } - arg_param_ = getParamFromIni_(getTool()); + arg_param_ = params_.copy(getTool() + ":"); - tool_desc_->setText(arg_param_.getSectionDescription(getTool()).toQString()); + tool_desc_->setText(String(arg_param_.getSectionDescription(getTool())).toQString()); vis_param_ = arg_param_.copy(getTool() + ":1:", true); vis_param_.remove("log"); vis_param_.remove("no_progress"); diff --git a/src/openms_gui/source/VISUAL/LayerData.cpp b/src/openms_gui/source/VISUAL/LayerData.cpp index 53bd486ae61..77dfbed2190 100644 --- a/src/openms_gui/source/VISUAL/LayerData.cpp +++ b/src/openms_gui/source/VISUAL/LayerData.cpp @@ -92,7 +92,7 @@ namespace OpenMS peak_map_(new ExperimentType()), on_disc_peaks(new OnDiscMSExperiment()), chromatogram_map_(new ExperimentType()), - current_spectrum_(0), + current_spectrum_idx_(0), cached_spectrum_() { annotations_1d.resize(1); @@ -168,13 +168,13 @@ namespace OpenMS void LayerData::updateCache_() { - if (peak_map_->getNrSpectra() > current_spectrum_ && (*peak_map_)[current_spectrum_].size() > 0) + if (peak_map_->getNrSpectra() > current_spectrum_idx_ && (*peak_map_)[current_spectrum_idx_].size() > 0) { - cached_spectrum_ = (*peak_map_)[current_spectrum_]; + cached_spectrum_ = (*peak_map_)[current_spectrum_idx_]; } - else if (on_disc_peaks->getNrSpectra() > current_spectrum_) + else if (on_disc_peaks->getNrSpectra() > current_spectrum_idx_) { - cached_spectrum_ = on_disc_peaks->getSpectrum(current_spectrum_); + cached_spectrum_ = on_disc_peaks->getSpectrum(current_spectrum_idx_); } } @@ -238,7 +238,7 @@ namespace OpenMS const LayerData::ExperimentType::SpectrumType LayerData::getSpectrum(Size spectrum_idx) const { - if (spectrum_idx == current_spectrum_) return cached_spectrum_; + if (spectrum_idx == current_spectrum_idx_) return cached_spectrum_; if ((*peak_map_)[spectrum_idx].size() > 0) { @@ -257,7 +257,7 @@ namespace OpenMS if (getPeakData() == nullptr || getPeakData()->empty() || type != LayerData::DT_PEAK) { return; } // get mutable access to the spectrum - MSSpectrum & spectrum = getPeakDataMuteable()->getSpectrum(current_spectrum_); + MSSpectrum & spectrum = getPeakDataMuteable()->getSpectrum(current_spectrum_idx_); int ms_level = spectrum.getMSLevel(); @@ -291,7 +291,7 @@ namespace OpenMS else // PeptideIdentifications are empty, create new PepIDs and PeptideHits to store the PeakAnnotations { // copy user annotations to fragment annotation vector - const Annotations1DContainer & las = getAnnotations(current_spectrum_); + const Annotations1DContainer & las = getAnnotations(current_spectrum_idx_); // no annotations so we don't need to synchronize bool has_peak_annotation(false); @@ -344,7 +344,7 @@ namespace OpenMS bool annotations_changed(false); // regular expression for a charge at the end of the annotation - QRegExp reg_exp("([\\+|\\-]\\d+)$"); + QRegExp reg_exp(R"(([\+|\-]\d+)$)"); // for each annotation item on the canvas for (auto& a : las) @@ -438,7 +438,7 @@ namespace OpenMS if (peptide_id_index == -1 || peptide_hit_index == -1) { return; } // get mutable access to the spectrum - MSSpectrum & spectrum = getPeakDataMuteable()->getSpectrum(current_spectrum_); + MSSpectrum & spectrum = getPeakDataMuteable()->getSpectrum(current_spectrum_idx_); int ms_level = spectrum.getMSLevel(); // wrong MS level diff --git a/src/openms_gui/source/VISUAL/LayerListView.cpp b/src/openms_gui/source/VISUAL/LayerListView.cpp index db98e10ffe3..3c6fc0de9b3 100644 --- a/src/openms_gui/source/VISUAL/LayerListView.cpp +++ b/src/openms_gui/source/VISUAL/LayerListView.cpp @@ -99,7 +99,7 @@ namespace OpenMS if (is_1d_view) { QPixmap icon(7, 7); - icon.fill(QColor(layer.param.getValue("peak_color").toQString())); + icon.fill(QColor(String(layer.param.getValue("peak_color").toString()).toQString())); item->setIcon(icon); } else diff --git a/src/openms_gui/source/VISUAL/ParamEditor.cpp b/src/openms_gui/source/VISUAL/ParamEditor.cpp index 65f7f538545..7858a39a99d 100644 --- a/src/openms_gui/source/VISUAL/ParamEditor.cpp +++ b/src/openms_gui/source/VISUAL/ParamEditor.cpp @@ -506,11 +506,11 @@ namespace OpenMS { item = new QTreeWidgetItem(parent); //name - item->setText(0, it2->name.toQString()); + item->setText(0, String(it2->name).toQString()); item->setTextColor(0, Qt::darkGray); // color of nodes with children //description - item->setData(1, Qt::UserRole, it2->description.toQString()); + item->setData(1, Qt::UserRole, String(it2->description).toQString()); //role item->setData(0, Qt::UserRole, NODE); //flags @@ -561,36 +561,36 @@ namespace OpenMS item->setData(0, Qt::UserRole, NORMAL_ITEM); } // name - item->setText(0, it->name.toQString()); + item->setText(0, String(it->name).toQString()); // value - if (it->value.valueType() == DataValue::STRING_LIST) + if (it->value.valueType() == ParamValue::STRING_LIST) { - item->setText(1, QString("[%1]").arg(GUIHelpers::convert(it->value.toStringList()).join(",\n"))); + item->setText(1, QString("[%1]").arg(GUIHelpers::convert(ListUtils::toStringList(it->value.toStringVector())).join(",\n"))); } - else if (it->value.valueType() == DataValue::INT_LIST) + else if (it->value.valueType() == ParamValue::INT_LIST) { - item->setText(1, QString("[%1]").arg(GUIHelpers::convert(ListUtils::toStringList(it->value.toIntList())).join(",\n"))); + item->setText(1, QString("[%1]").arg(GUIHelpers::convert(ListUtils::toStringList(it->value.toIntVector())).join(",\n"))); } - else if (it->value.valueType() == DataValue::DOUBLE_LIST) + else if (it->value.valueType() == ParamValue::DOUBLE_LIST) { - item->setText(1, QString("[%1]").arg(GUIHelpers::convert(ListUtils::toStringList(it->value.toDoubleList())).join(",\n"))); + item->setText(1, QString("[%1]").arg(GUIHelpers::convert(ListUtils::toStringList(it->value.toDoubleVector())).join(",\n"))); } else { - item->setText(1, String(it->value).toQString()); + item->setText(1, String(it->value.toString()).toQString()); } // type switch (it->value.valueType()) { - case DataValue::INT_VALUE: + case ParamValue::INT_VALUE: item->setText(2, "int"); break; - case DataValue::DOUBLE_VALUE: + case ParamValue::DOUBLE_VALUE: item->setText(2, "float"); break; - case DataValue::STRING_VALUE: + case ParamValue::STRING_VALUE: if (it->tags.count("input file")) { item->setText(2, "input file"); @@ -605,7 +605,7 @@ namespace OpenMS } break; - case DataValue::STRING_LIST: + case ParamValue::STRING_LIST: if (it->tags.count("input file")) { item->setText(2, "input file list"); @@ -620,11 +620,11 @@ namespace OpenMS } break; - case DataValue::INT_LIST: + case ParamValue::INT_LIST: item->setText(2, "int list"); break; - case DataValue::DOUBLE_LIST: + case ParamValue::DOUBLE_LIST: item->setText(2, "double list"); break; @@ -634,8 +634,8 @@ namespace OpenMS //restrictions (displayed and internal for easier parsing) switch (it->value.valueType()) { - case DataValue::INT_VALUE: - case DataValue::INT_LIST: + case ParamValue::INT_VALUE: + case ParamValue::INT_LIST: { String drest = "", irest = ""; bool min_set = (it->min_int != -numeric_limits::max()); @@ -661,8 +661,8 @@ namespace OpenMS } break; - case DataValue::DOUBLE_VALUE: - case DataValue::DOUBLE_LIST: + case ParamValue::DOUBLE_VALUE: + case ParamValue::DOUBLE_LIST: { String drest = "", irest = ""; bool min_set = (it->min_float != -numeric_limits::max()); @@ -688,8 +688,8 @@ namespace OpenMS } break; - case DataValue::STRING_VALUE: - case DataValue::STRING_LIST: + case ParamValue::STRING_VALUE: + case ParamValue::STRING_LIST: { String irest = ListUtils::concatenate(it->valid_strings, ","); if (!irest.empty()) @@ -709,9 +709,9 @@ namespace OpenMS break; } - // description - item->setData(1, Qt::UserRole, it->description.toQString()); - // flags + //description + item->setData(1, Qt::UserRole, String(it->description).toQString()); + //flags if (param_ != nullptr) { item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable); @@ -788,7 +788,7 @@ namespace OpenMS String description = child->data(1, Qt::UserRole).toString(); - StringList tag_list; + std::vector tag_list; try // might throw ElementNotFound { tag_list = param_->getTags(path); @@ -829,8 +829,7 @@ namespace OpenMS String restrictions = child->data(2, Qt::UserRole).toString(); if (restrictions != "") { - std::vector parts; - restrictions.split(',', parts); + std::vector parts = ListUtils::create(restrictions); param_->setValidStrings(path, parts); } } @@ -840,8 +839,7 @@ namespace OpenMS String restrictions = child->data(2, Qt::UserRole).toString(); if (restrictions != "") { - std::vector parts; - restrictions.split(',', parts); + std::vector parts = ListUtils::create(restrictions); param_->setValidStrings(path, parts); } } @@ -851,8 +849,7 @@ namespace OpenMS String restrictions = child->data(2, Qt::UserRole).toString(); if (restrictions != "") { - std::vector parts; - restrictions.split(',', parts); + std::vector parts = ListUtils::create(restrictions); param_->setValidStrings(path, parts); } } @@ -875,19 +872,14 @@ namespace OpenMS } String list; list = child->text(1).mid(1, child->text(1).length() - 2); - StringList rlist = ListUtils::create(list); - for (UInt i = 0; i < rlist.size(); ++i) - { - rlist[i] = rlist[i].trim(); - } + std::vector rlist = ListUtils::create(list); if (child->text(2) == "string list") { param_->setValue(path, rlist, description, tag_list); String restrictions = child->data(2, Qt::UserRole).toString(); if (restrictions != "") { - vector parts; - restrictions.split(',', parts); + vector parts = ListUtils::create(restrictions); param_->setValidStrings(path, parts); } } @@ -897,8 +889,7 @@ namespace OpenMS String restrictions = child->data(2, Qt::UserRole).toString(); if (restrictions != "") { - vector parts; - restrictions.split(',', parts); + std::vector parts = ListUtils::create(restrictions); param_->setValidStrings(path, parts); } } @@ -908,14 +899,13 @@ namespace OpenMS String restrictions = child->data(2, Qt::UserRole).toString(); if (restrictions != "") { - vector parts; - restrictions.split(',', parts); + std::vector parts = ListUtils::create(restrictions); param_->setValidStrings(path, parts); } } else if (child->text(2) == "double list") { - param_->setValue(path, ListUtils::create(rlist), description, tag_list); + param_->setValue(path, ListUtils::create(ListUtils::toStringList(rlist)), description, tag_list); String restrictions = child->data(2, Qt::UserRole).toString(); vector parts; if (restrictions.split(' ', parts)) @@ -932,7 +922,7 @@ namespace OpenMS } else if (child->text(2) == "int list") { - param_->setValue(path, ListUtils::create(rlist), description, tag_list); + param_->setValue(path, ListUtils::create(ListUtils::toStringList(rlist)), description, tag_list); String restrictions = child->data(2, Qt::UserRole).toString(); vector parts; if (restrictions.split(' ', parts)) diff --git a/src/openms_gui/source/VISUAL/Plot1DCanvas.cpp b/src/openms_gui/source/VISUAL/Plot1DCanvas.cpp index 8a248d6f6e3..59491f806af 100644 --- a/src/openms_gui/source/VISUAL/Plot1DCanvas.cpp +++ b/src/openms_gui/source/VISUAL/Plot1DCanvas.cpp @@ -747,7 +747,7 @@ namespace OpenMS // clear painter->fillRect(0, 0, this->width(), this->height(), - QColor(param_.getValue("background_color").toQString())); + QColor(String(param_.getValue("background_color").toString()).toQString())); // only fill background if no layer is present if (getLayerCount() == 0) @@ -770,8 +770,8 @@ namespace OpenMS const ExperimentType::SpectrumType& spectrum = layer.getCurrentSpectrum(); // get default icon and peak color - QPen icon_pen = QPen(QColor(layer.param.getValue("icon_color").toQString()), 1); - QPen pen(QColor(layer.param.getValue("peak_color").toQString()), 1); + QPen icon_pen = QPen(QColor(String(layer.param.getValue("icon_color").toString()).toQString()), 1); + QPen pen(QColor(String(layer.param.getValue("peak_color").toString()).toQString()), 1); pen.setStyle(peak_penstyle_[i]); // TODO option for variable pen width @@ -901,7 +901,7 @@ namespace OpenMS if (tmp != spectrum.end()) { PointType position(xpos, std::max(tmp->getIntensity() - 100, tmp->getIntensity() * 0.8)); - Annotation1DPeakItem item = Annotation1DPeakItem(position, layer.getName().toQString(), QColor(layer.param.getValue("peak_color").toQString())); + Annotation1DPeakItem item = Annotation1DPeakItem(position, layer.getName().toQString(), QColor(String(layer.param.getValue("peak_color").toString()).toQString())); item.draw(this, *painter); } } @@ -998,7 +998,7 @@ namespace OpenMS } const ExperimentType::PeakType& sel = spec[peak.peak]; - painter.setPen(QPen(QColor(param_.getValue("highlighted_peak_color").toQString()), 2)); + painter.setPen(QPen(QColor(String(param_.getValue("highlighted_peak_color").toString()).toQString()), 2)); updatePercentageFactor_(layer_index); @@ -1049,7 +1049,7 @@ namespace OpenMS QVector dashes; dashes << 5 << 5 << 1 << 5; pen.setDashPattern(dashes); - pen.setColor(QColor(param_.getValue("highlighted_peak_color").toQString())); + pen.setColor(QColor(String(param_.getValue("highlighted_peak_color").toString()).toQString())); painter.save(); painter.setPen(pen); painter.drawLine(from, to); @@ -1060,7 +1060,7 @@ namespace OpenMS { LayerData& layer = getLayer(layer_index); updatePercentageFactor_(layer_index); - QColor col{ QColor(layer.param.getValue("annotation_color").toQString()) }; + QColor col{ QColor(String(layer.param.getValue("annotation_color").toString()).toQString()) }; // 0: default pen; 1: selected pen QPen pen[2] = { col, col.lighter() }; @@ -1409,19 +1409,19 @@ namespace OpenMS ColorSelector* bg_color = dlg.findChild("bg_color"); ColorSelector* selected_color = dlg.findChild("selected_color"); - peak_color->setColor(QColor(layer.param.getValue("peak_color").toQString())); - icon_color->setColor(QColor(layer.param.getValue("icon_color").toQString())); - annotation_color->setColor(QColor(layer.param.getValue("annotation_color").toQString())); - bg_color->setColor(QColor(param_.getValue("background_color").toQString())); - selected_color->setColor(QColor(param_.getValue("highlighted_peak_color").toQString())); + peak_color->setColor(QColor(String(layer.param.getValue("peak_color").toString()).toQString())); + icon_color->setColor(QColor(String(layer.param.getValue("icon_color").toString()).toQString())); + annotation_color->setColor(QColor(String(layer.param.getValue("annotation_color").toString()).toQString())); + bg_color->setColor(QColor(String(param_.getValue("background_color").toString()).toQString())); + selected_color->setColor(QColor(String(param_.getValue("highlighted_peak_color").toString()).toQString())); if (dlg.exec()) { - layer.param.setValue("peak_color", peak_color->getColor().name()); - layer.param.setValue("icon_color", icon_color->getColor().name()); - layer.param.setValue("annotation_color", annotation_color->getColor().name()); - param_.setValue("background_color", bg_color->getColor().name()); - param_.setValue("highlighted_peak_color", selected_color->getColor().name()); + layer.param.setValue("peak_color", peak_color->getColor().name().toStdString()); + layer.param.setValue("icon_color", icon_color->getColor().name().toStdString()); + layer.param.setValue("annotation_color", annotation_color->getColor().name().toStdString()); + param_.setValue("background_color", bg_color->getColor().name().toStdString()); + param_.setValue("highlighted_peak_color", selected_color->getColor().name().toStdString()); emit preferencesChange(); } @@ -1608,7 +1608,7 @@ namespace OpenMS else if (result->text() == "Add peak annotation mz") { QString label = String::number(getCurrentLayer().getCurrentSpectrum()[near_peak.peak].getMZ(), 4).toQString(); - addPeakAnnotation(near_peak, label, getCurrentLayer().param.getValue("peak_color").toQString()); + addPeakAnnotation(near_peak, label, String(getCurrentLayer().param.getValue("peak_color").toString()).toQString()); } else if (result->text() == "Reset alignment") { @@ -1672,7 +1672,7 @@ namespace OpenMS QString text = QInputDialog::getText(this, "Add peak annotation", "Enter text:", QLineEdit::Normal, "", &ok); if (ok && !text.isEmpty()) { - addPeakAnnotation(near_peak, text, QColor(getCurrentLayer().param.getValue("peak_color").toQString())); + addPeakAnnotation(near_peak, text, QColor(String(getCurrentLayer().param.getValue("peak_color").toString()).toQString())); } } @@ -1692,7 +1692,7 @@ namespace OpenMS const LayerData& layer = getCurrentLayer(); //determine proposed filename - String proposed_name = param_.getValue("default_path"); + String proposed_name = param_.getValue("default_path").toString(); if (!visible && !layer.filename.empty()) { proposed_name = layer.filename; diff --git a/src/openms_gui/source/VISUAL/Plot2DCanvas.cpp b/src/openms_gui/source/VISUAL/Plot2DCanvas.cpp index a682879452f..112ed9f8a94 100644 --- a/src/openms_gui/source/VISUAL/Plot2DCanvas.cpp +++ b/src/openms_gui/source/VISUAL/Plot2DCanvas.cpp @@ -97,12 +97,12 @@ namespace OpenMS defaults_.setMaxInt("interpolation_steps", 1000); defaults_.setValue("dot:gradient", "Linear|0,#eeeeee;1,#ffea00;6,#ff0000;14,#aa00ff;23,#5500ff;100,#000000", "Multi-color gradient for peaks."); defaults_.setValue("dot:feature_icon", "circle", "Icon used for features and consensus features."); - defaults_.setValidStrings("dot:feature_icon", ListUtils::create("diamond,square,circle,triangle")); + defaults_.setValidStrings("dot:feature_icon", {"diamond","square","circle","triangle"}); defaults_.setValue("dot:feature_icon_size", 4, "Icon size used for features and consensus features."); defaults_.setMinInt("dot:feature_icon_size", 1); defaults_.setMaxInt("dot:feature_icon_size", 999); defaults_.setValue("mapping_of_mz_to", "y_axis", "Determines which axis is the m/z axis."); - defaults_.setValidStrings("mapping_of_mz_to", ListUtils::create("x_axis,y_axis")); + defaults_.setValidStrings("mapping_of_mz_to", {"x_axis","y_axis"}); defaultsToParam_(); setName("Plot2DCanvas"); setParameters(preferences); @@ -113,7 +113,7 @@ namespace OpenMS projection_rt_.resize(1); //set preferences and update widgets accordingly - if (String(param_.getValue("mapping_of_mz_to")) != "x_axis") + if (param_.getValue("mapping_of_mz_to") != "x_axis") { mzToXAxis(false); } @@ -435,7 +435,7 @@ namespace OpenMS } else if (layer.type == LayerData::DT_CONSENSUS) // consensus features { - String icon = layer.param.getValue("dot:feature_icon"); + String icon = layer.param.getValue("dot:feature_icon").toString(); Size icon_size = layer.param.getValue("dot:feature_icon_size"); for (ConsensusMapType::ConstIterator i = layer.getConsensusMap()->begin(); @@ -717,7 +717,7 @@ namespace OpenMS Int image_height = buffer_.height(); int line_spacing = QFontMetrics(painter.font()).lineSpacing(); - String icon = layer.param.getValue("dot:feature_icon"); + String icon = layer.param.getValue("dot:feature_icon").toString(); Size icon_size = layer.param.getValue("dot:feature_icon_size"); bool show_label = (layer.label != LayerData::L_NONE); UInt num = 0; @@ -1489,7 +1489,7 @@ namespace OpenMS { QPainter painter; painter.begin(this); - painter.fillRect(0, 0, this->width(), this->height(), QColor(param_.getValue("background_color").toQString())); + painter.fillRect(0, 0, this->width(), this->height(), QColor(String(param_.getValue("background_color").toString()).toQString())); painter.end(); e->accept(); return; @@ -1524,7 +1524,7 @@ namespace OpenMS // recalculate snap factor recalculateSnapFactor_(); - buffer_.fill(QColor(param_.getValue("background_color").toQString()).rgb()); + buffer_.fill(QColor(String(param_.getValue("background_color").toString()).toQString()).rgb()); painter.begin(&buffer_); QTime layer_timer; @@ -2628,7 +2628,7 @@ namespace OpenMS QComboBox * feature_icon = dlg.findChild("feature_icon"); QSpinBox * feature_icon_size = dlg.findChild("feature_icon_size"); - bg_color->setColor(QColor(param_.getValue("background_color").toQString())); + bg_color->setColor(QColor(String(param_.getValue("background_color").toString()).toQString())); if (isMzToXAxis()) { mapping->setCurrentIndex(0); @@ -2638,13 +2638,13 @@ namespace OpenMS mapping->setCurrentIndex(1); } gradient->gradient().fromString(layer.param.getValue("dot:gradient")); - feature_icon->setCurrentIndex(feature_icon->findText(layer.param.getValue("dot:feature_icon").toQString())); + feature_icon->setCurrentIndex(feature_icon->findText(String(layer.param.getValue("dot:feature_icon").toString()).toQString())); feature_icon_size->setValue((int)layer.param.getValue("dot:feature_icon_size")); if (dlg.exec()) { - param_.setValue("background_color", bg_color->getColor().name()); - layer.param.setValue("dot:feature_icon", feature_icon->currentText()); + param_.setValue("background_color", bg_color->getColor().name().toStdString()); + layer.param.setValue("dot:feature_icon", feature_icon->currentText().toStdString()); layer.param.setValue("dot:feature_icon_size", feature_icon_size->value()); if ((mapping->currentIndex() == 0 && !isMzToXAxis()) || (mapping->currentIndex() == 1 && isMzToXAxis())) { @@ -2669,7 +2669,7 @@ namespace OpenMS const LayerData & layer = getCurrentLayer(); //determine proposed filename - String proposed_name = param_.getValue("default_path"); + String proposed_name = param_.getValue("default_path").toString(); if (visible == false && layer.filename != "") { proposed_name = layer.filename; diff --git a/src/openms_gui/source/VISUAL/Plot3DCanvas.cpp b/src/openms_gui/source/VISUAL/Plot3DCanvas.cpp index 915e2707179..698fb1c51f8 100644 --- a/src/openms_gui/source/VISUAL/Plot3DCanvas.cpp +++ b/src/openms_gui/source/VISUAL/Plot3DCanvas.cpp @@ -207,14 +207,14 @@ namespace OpenMS MultiGradientSelector * gradient = dlg.findChild("gradient"); QSpinBox * width = dlg.findChild("width"); - bg_color->setColor(QColor(param_.getValue("background_color").toQString())); + bg_color->setColor(QColor(String(param_.getValue("background_color").toString()).toQString())); shade->setCurrentIndex(layer.param.getValue("dot:shade_mode")); gradient->gradient().fromString(layer.param.getValue("dot:gradient")); width->setValue(UInt(layer.param.getValue("dot:line_width"))); if (dlg.exec()) { - param_.setValue("background_color", bg_color->getColor().name()); + param_.setValue("background_color", bg_color->getColor().name().toStdString()); layer.param.setValue("dot:shade_mode", shade->currentIndex()); layer.param.setValue("dot:gradient", gradient->gradient().toString()); layer.param.setValue("dot:line_width", width->value()); @@ -308,7 +308,7 @@ namespace OpenMS const LayerData & layer = getCurrentLayer(); //determine proposed filename - String proposed_name = param_.getValue("default_path"); + String proposed_name = param_.getValue("default_path").toString(); if (visible == false && layer.filename != "") { proposed_name = layer.filename; diff --git a/src/openms_gui/source/VISUAL/Plot3DOpenGLCanvas.cpp b/src/openms_gui/source/VISUAL/Plot3DOpenGLCanvas.cpp index 90d9fb36129..0faf5b81abc 100644 --- a/src/openms_gui/source/VISUAL/Plot3DOpenGLCanvas.cpp +++ b/src/openms_gui/source/VISUAL/Plot3DOpenGLCanvas.cpp @@ -192,7 +192,7 @@ namespace OpenMS glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - QColor color(canvas_3d_.param_.getValue("background_color").toQString()); + QColor color(String(canvas_3d_.param_.getValue("background_color").toString()).toQString()); qglClearColor_(color); calculateGridLines_(); @@ -498,7 +498,7 @@ namespace OpenMS GLuint list = glGenLists(1); glNewList(list, GL_COMPILE); glBegin(GL_QUADS); - QColor color(canvas_3d_.param_.getValue("background_color").toQString()); + QColor color(String(canvas_3d_.param_.getValue("background_color").toString()).toQString()); qglColor_(color); glVertex3d(-corner_, -corner_ - 2.0, -near_ - 2 * corner_); glVertex3d(-corner_, -corner_ - 2.0, -far_ + 2 * corner_); diff --git a/src/openms_gui/source/VISUAL/RecentFilesMenu.cpp b/src/openms_gui/source/VISUAL/RecentFilesMenu.cpp index aa5921ac2ac..74b9e48a752 100644 --- a/src/openms_gui/source/VISUAL/RecentFilesMenu.cpp +++ b/src/openms_gui/source/VISUAL/RecentFilesMenu.cpp @@ -85,7 +85,7 @@ namespace OpenMS unsigned count{ 0 }; for (Param::ParamIterator it = filenames.begin(); it != filenames.end(); ++it) { - QString filename = it->value.toQString(); + QString filename = String(it->value.toString()).toQString(); if (File::exists(filename)) { rfiles.append(filename); @@ -102,7 +102,7 @@ namespace OpenMS int i{ 0 }; for (const auto& f : recent_files_) { - p.setValue(String(i), f); + p.setValue(String(i), f.toStdString()); ++i; } return p; diff --git a/src/openms_gui/source/VISUAL/SpectraTreeTab.cpp b/src/openms_gui/source/VISUAL/SpectraTreeTab.cpp index 1bc4b400aab..f92cacfc155 100644 --- a/src/openms_gui/source/VISUAL/SpectraTreeTab.cpp +++ b/src/openms_gui/source/VISUAL/SpectraTreeTab.cpp @@ -434,7 +434,7 @@ namespace OpenMS // type or by the flag which is set). else if (cl.type == LayerData::DT_CHROMATOGRAM || cl.chromatogram_flag_set()) { - LayerData::ConstExperimentSharedPtrType exp = (cl.chromatogram_flag_set() + LayerData::ConstExperimentSharedPtrType exp = (cl.chromatogram_flag_set() // if set, the actual full data is in getChromatogramData; the peakdata only contains a single spec ? cl.getChromatogramData() : cl.getPeakData()); @@ -483,10 +483,14 @@ namespace OpenMS } int precursor_idx = 0; - for (const auto& pc_indices : map_precursor_to_chrom_idx) + for (const auto& [pc, indx] : map_precursor_to_chrom_idx) { - const auto& pc = pc_indices.first; - const auto& indx = pc_indices.second; + // Top level precursor entry + toplevel_item = new QTreeWidgetItem(); + toplevel_item->setText(ClmnChrom::TYPE, "Peptide"); + toplevel_item->setData(ClmnChrom::TYPE, Qt::UserRole, vecToList(indx)); + toplevel_item->setData(ClmnChrom::CHROM_INDEX, Qt::DisplayRole, precursor_idx++); + toplevel_item->setData(ClmnChrom::MZ, Qt::DisplayRole, pc.getMZ()); // Show the peptide sequence if available, otherwise show the m/z and charge only QString description; if (pc.metaValueExists("peptide_sequence")) @@ -497,16 +501,7 @@ namespace OpenMS { description = String(pc.getMetaValue("description")).toQString(); } - - // Top level precursor entry - toplevel_item = new QTreeWidgetItem(); - toplevel_item->setText(ClmnChrom::TYPE, "Peptide"); - toplevel_item->setData(ClmnChrom::TYPE, Qt::UserRole, vecToList(indx)); - toplevel_item->setData(ClmnChrom::CHROM_INDEX, Qt::DisplayRole, precursor_idx++); - toplevel_item->setData(ClmnChrom::MZ, Qt::DisplayRole, pc.getMZ()); toplevel_item->setText(ClmnChrom::DESCRIPTION, description); - //toplevel_item->setText(ClmnChrom::RT_START, QString::number(prod_it->second[0].front().getRT())); - //toplevel_item->setText(ClmnChrom::RT_END, QString::number(prod_it->second[0].back().getRT())); toplevel_item->setData(ClmnChrom::CHARGE, Qt::DisplayRole, pc.getCharge()); toplevel_items.push_back(toplevel_item); @@ -597,7 +592,7 @@ namespace OpenMS } - bool SpectraTreeTab::getSelectedScan(MSExperiment& exp) const + bool SpectraTreeTab::getSelectedScan(MSExperiment& exp, LayerData::DataType& current_type) const { exp.clear(true); QTreeWidgetItem* item = spectra_treewidget_->currentItem(); @@ -606,10 +601,12 @@ namespace OpenMS int index = item->data(ClmnPeak::SPEC_INDEX, Qt::DisplayRole).toInt(); if (spectra_treewidget_->headerItem()->text(ClmnChrom::MZ) == ClmnChrom::HEADER_NAMES[ClmnChrom::MZ]) { // we currently show chromatogram data + current_type = LayerData::DT_CHROMATOGRAM; exp.addChromatogram(last_peakmap_->getChromatograms()[index]); } else { + current_type = LayerData::DT_PEAK; exp.addSpectrum(last_peakmap_->getSpectra()[index]); } return true; diff --git a/src/openms_gui/source/VISUAL/TOPPASOutputFileListVertex.cpp b/src/openms_gui/source/VISUAL/TOPPASOutputFileListVertex.cpp index 9a3367f1b85..a27d059b04f 100644 --- a/src/openms_gui/source/VISUAL/TOPPASOutputFileListVertex.cpp +++ b/src/openms_gui/source/VISUAL/TOPPASOutputFileListVertex.cpp @@ -188,7 +188,7 @@ namespace OpenMS String out_type = source_output_files[e->getSourceOutParam()].param_name + "_type"; if (p.exists(out_type)) { - ft = FileTypes::nameToType(p.getValue(out_type)); + ft = FileTypes::nameToType(p.getValue(out_type).toString()); } } diff --git a/src/openms_gui/source/VISUAL/TOPPASResources.cpp b/src/openms_gui/source/VISUAL/TOPPASResources.cpp index 3d27a4503e9..20c45cceae0 100644 --- a/src/openms_gui/source/VISUAL/TOPPASResources.cpp +++ b/src/openms_gui/source/VISUAL/TOPPASResources.cpp @@ -74,17 +74,17 @@ namespace OpenMS for (Param::ParamIterator it = load_param.begin(); it != load_param.end(); ++it) { StringList substrings; - it.getName().split(':', substrings); + String(it.getName()).split(':', substrings); if (substrings.size() != 2 || substrings.back() != "url_list" || - (it->value).valueType() != DataValue::STRING_LIST) + (it->value).valueType() != ParamValue::STRING_LIST) { std::cerr << "Invalid file format." << std::endl; return; } QString key = (substrings[0]).toQString(); - StringList url_list = (it->value); + StringList url_list = ListUtils::toStringList(it->value); QList resource_list; for (StringList::const_iterator it = url_list.begin(); it != url_list.end(); ++it) { @@ -108,12 +108,12 @@ namespace OpenMS { const String& key = String(it->first); const QList& resource_list = it->second; - StringList url_list; + std::vector url_list; foreach(const TOPPASResource &res, resource_list) { - url_list.push_back(String(res.getURL().toString())); + url_list.push_back(String(res.getURL().toString().toStdString())); } - save_param.setValue(key + ":url_list", DataValue(url_list)); + save_param.setValue(key + ":url_list", url_list); } ParamXMLFile paramFile; diff --git a/src/openms_gui/source/VISUAL/TOPPASScene.cpp b/src/openms_gui/source/VISUAL/TOPPASScene.cpp index 478bb48a44c..4b4984ec4f7 100644 --- a/src/openms_gui/source/VISUAL/TOPPASScene.cpp +++ b/src/openms_gui/source/VISUAL/TOPPASScene.cpp @@ -692,10 +692,10 @@ namespace OpenMS { Param save_param; - save_param.setValue("info:version", DataValue(VersionInfo::getVersion())); - save_param.setValue("info:num_vertices", DataValue(vertices_.size())); - save_param.setValue("info:num_edges", DataValue(edges_.size())); - save_param.setValue("info:description", DataValue(String("description_text_) + String("]]>"))); + save_param.setValue("info:version", VersionInfo::getVersion()); + save_param.setValue("info:num_vertices", vertices_.size()); + save_param.setValue("info:num_edges", edges_.size()); + save_param.setValue("info:description", String("description_text_) + String("]]>")); // store all vertices (together with all parameters) foreach(TOPPASVertex * tv, vertices_) @@ -703,7 +703,7 @@ namespace OpenMS String id(tv->getTopoNr() - 1); // common for all vertices - save_param.setValue("vertices:" + id + ":recycle_output", DataValue(tv->isRecyclingEnabled() ? "true" : "false")); + save_param.setValue("vertices:" + id + ":recycle_output", tv->isRecyclingEnabled() ? "true" : "false"); // vertex subclasses TOPPASInputFileListVertex* iflv = qobject_cast(tv); @@ -712,56 +712,56 @@ namespace OpenMS // store file names relative to toppas file QDir save_dir(File::path(file).toQString()); const QStringList& files_qt = iflv->getFileNames(); - StringList files; + std::vector files; foreach(const QString &file_qt, files_qt) { - files.push_back(save_dir.relativeFilePath(file_qt)); + files.push_back(save_dir.relativeFilePath(file_qt).toStdString()); } - save_param.setValue("vertices:" + id + ":toppas_type", DataValue("input file list")); - save_param.setValue("vertices:" + id + ":file_names", DataValue(files)); - save_param.setValue("vertices:" + id + ":x_pos", DataValue(tv->x())); - save_param.setValue("vertices:" + id + ":y_pos", DataValue(tv->y())); + save_param.setValue("vertices:" + id + ":toppas_type", "input file list"); + save_param.setValue("vertices:" + id + ":file_names", files); + save_param.setValue("vertices:" + id + ":x_pos", tv->x()); + save_param.setValue("vertices:" + id + ":y_pos", tv->y()); continue; } TOPPASOutputFileListVertex* oflv = qobject_cast(tv); if (oflv) { - save_param.setValue("vertices:" + id + ":toppas_type", DataValue("output file list")); - save_param.setValue("vertices:" + id + ":x_pos", DataValue(tv->x())); - save_param.setValue("vertices:" + id + ":y_pos", DataValue(tv->y())); - save_param.setValue("vertices:" + id + ":output_folder_name", oflv->getOutputFolderName()); + save_param.setValue("vertices:" + id + ":toppas_type", "output file list"); + save_param.setValue("vertices:" + id + ":x_pos", tv->x()); + save_param.setValue("vertices:" + id + ":y_pos", tv->y()); + save_param.setValue("vertices:" + id + ":output_folder_name", oflv->getOutputFolderName().toStdString()); continue; } TOPPASToolVertex* ttv = qobject_cast(tv); if (ttv) { - save_param.setValue("vertices:" + id + ":toppas_type", DataValue("tool")); - save_param.setValue("vertices:" + id + ":tool_name", DataValue(ttv->getName())); - save_param.setValue("vertices:" + id + ":tool_type", DataValue(ttv->getType())); + save_param.setValue("vertices:" + id + ":toppas_type", "tool"); + save_param.setValue("vertices:" + id + ":tool_name", ttv->getName()); + save_param.setValue("vertices:" + id + ":tool_type", ttv->getType()); save_param.insert("vertices:" + id + ":parameters:", ttv->getParam()); - save_param.setValue("vertices:" + id + ":x_pos", DataValue(tv->x())); - save_param.setValue("vertices:" + id + ":y_pos", DataValue(tv->y())); + save_param.setValue("vertices:" + id + ":x_pos", tv->x()); + save_param.setValue("vertices:" + id + ":y_pos", tv->y()); continue; } TOPPASMergerVertex* mv = qobject_cast(tv); if (mv) { - save_param.setValue("vertices:" + id + ":toppas_type", DataValue("merger")); - save_param.setValue("vertices:" + id + ":x_pos", DataValue(tv->x())); - save_param.setValue("vertices:" + id + ":y_pos", DataValue(tv->y())); - save_param.setValue("vertices:" + id + ":round_based", DataValue(mv->roundBasedMode() ? "true" : "false")); + save_param.setValue("vertices:" + id + ":toppas_type", "merger"); + save_param.setValue("vertices:" + id + ":x_pos", tv->x()); + save_param.setValue("vertices:" + id + ":y_pos", tv->y()); + save_param.setValue("vertices:" + id + ":round_based", mv->roundBasedMode() ? "true" : "false"); continue; } TOPPASSplitterVertex* sv = qobject_cast(tv); if (sv) { - save_param.setValue("vertices:" + id + ":toppas_type", DataValue("splitter")); - save_param.setValue("vertices:" + id + ":x_pos", DataValue(tv->x())); - save_param.setValue("vertices:" + id + ":y_pos", DataValue(tv->y())); + save_param.setValue("vertices:" + id + ":toppas_type", "splitter"); + save_param.setValue("vertices:" + id + ":x_pos", tv->x()); + save_param.setValue("vertices:" + id + ":y_pos", tv->y()); continue; } } @@ -780,9 +780,9 @@ namespace OpenMS continue; } - save_param.setValue("edges:" + String(counter) + ":source/target:", DataValue(String(te->getSourceVertex()->getTopoNr() - 1) + "/" + String(te->getTargetVertex()->getTopoNr() - 1))); - //save_param.setValue("edges:"+String(counter)+":source_out_param:", DataValue(te->getSourceOutParam())); - //save_param.setValue("edges:"+String(counter)+":target_in_param:", DataValue(te->getTargetInParam())); + save_param.setValue("edges:" + String(counter) + ":source/target:", String(te->getSourceVertex()->getTopoNr() - 1) + "/" + String(te->getTargetVertex()->getTopoNr() - 1)); + //save_param.setValue("edges:"+String(counter)+":source_out_param:", te->getSourceOutParam())); + //save_param.setValue("edges:"+String(counter)+":target_in_param:", te->getTargetInParam())); QVector files; String v = "__no_name__"; if (te->getSourceOutParam() >= 0) @@ -795,7 +795,7 @@ namespace OpenMS v = files[te->getSourceOutParam()].param_name; } } - save_param.setValue("edges:" + String(counter) + ":source_out_param:", DataValue(v)); + save_param.setValue("edges:" + String(counter) + ":source_out_param:", v); v = "__no_name__"; if (te->getTargetInParam() >= 0) @@ -808,7 +808,7 @@ namespace OpenMS v = files[te->getTargetInParam()].param_name; } } - save_param.setValue("edges:" + String(counter) + ":target_in_param:", DataValue(v)); + save_param.setValue("edges:" + String(counter) + ":target_in_param:", v); ++counter; } @@ -851,7 +851,7 @@ namespace OpenMS String file_version = "1.8.0"; // default (were we did not have the tag) if (load_param.exists("info:version")) { - file_version = load_param.getValue("info:version"); + file_version = load_param.getValue("info:version").toString(); } VersionInfo::VersionDetails v_file = VersionInfo::VersionDetails::create(file_version); VersionInfo::VersionDetails v_this_low = VersionInfo::VersionDetails::create("1.9.0"); // last compatible TOPPAS file version @@ -902,7 +902,7 @@ namespace OpenMS if (load_param.exists("info:description")) { - String text = String(load_param.getValue("info:description")).toQString(); + String text = String(load_param.getValue("info:description").toString()).toQString(); text.substitute("", ""); description_text_ = text.trim().toQString(); @@ -917,7 +917,7 @@ namespace OpenMS for (Param::ParamIterator it = vertices_param.begin(); it != vertices_param.end(); ++it) { StringList substrings; - it.getName().split(':', substrings); + String(it.getName()).split(':', substrings); if (substrings.back() == "toppas_type") // next node (all nodes have a "toppas_type") { current_vertex = nullptr; @@ -927,7 +927,7 @@ namespace OpenMS if (current_type == "input file list") { - StringList file_names = vertices_param.getValue(current_id + ":file_names"); + StringList file_names = ListUtils::toStringList(vertices_param.getValue(current_id + ":file_names")); QStringList file_names_qt; for (StringList::const_iterator str_it = file_names.begin(); str_it != file_names.end(); ++str_it) @@ -948,7 +948,7 @@ namespace OpenMS // custom output folder if (vertices_param.exists(current_id + ":output_folder_name")) { - oflv->setOutputFolderName(vertices_param.getValue(current_id + ":output_folder_name").toQString()); + oflv->setOutputFolderName(String(vertices_param.getValue(current_id + ":output_folder_name").toString()).toQString()); } connectOutputVertexSignals(oflv); @@ -957,8 +957,8 @@ namespace OpenMS } else if (current_type == "tool") { - String tool_name = vertices_param.getValue(current_id + ":tool_name"); - String tool_type = vertices_param.getValue(current_id + ":tool_type"); + String tool_name = vertices_param.getValue(current_id + ":tool_name").toString(); + String tool_type = vertices_param.getValue(current_id + ":tool_type").toString(); Param param_param = vertices_param.copy(current_id + ":parameters:", true); TOPPASToolVertex* tv = new TOPPASToolVertex(tool_name, tool_type); tv->setParam(param_param); @@ -972,7 +972,7 @@ namespace OpenMS String rb = "true"; if (vertices_param.exists(current_id + ":round_based")) { - rb = vertices_param.getValue(current_id + ":round_based"); + rb = vertices_param.getValue(current_id + ":round_based").toString(); } TOPPASMergerVertex* mv = new TOPPASMergerVertex(rb == "true"); @@ -1001,7 +1001,7 @@ namespace OpenMS // vertex parameters: if (vertices_param.exists(current_id + ":recycle_output")) // only since TOPPAS 1.9, so does not need to exist { - String recycle = vertices_param.getValue(current_id + ":recycle_output"); + String recycle = vertices_param.getValue(current_id + ":recycle_output").toString(); current_vertex->setRecycling(recycle == "true" ? true : false); } @@ -1068,8 +1068,8 @@ namespace OpenMS addEdge(edge); - String source_out_param = (++it)->value; - String target_in_param = (++it)->value; + String source_out_param = (++it)->value.toString(); + String target_in_param = (++it)->value.toString(); if (pre_1_9_toppas) // just indices stored - no way we can check { edge->setSourceOutParam(source_out_param.toInt()); diff --git a/src/openms_gui/source/VISUAL/TOPPASToolVertex.cpp b/src/openms_gui/source/VISUAL/TOPPASToolVertex.cpp index 45c955e13e9..0ca709691af 100644 --- a/src/openms_gui/source/VISUAL/TOPPASToolVertex.cpp +++ b/src/openms_gui/source/VISUAL/TOPPASToolVertex.cpp @@ -182,7 +182,7 @@ namespace OpenMS QFile q_old_ini(old_ini_file); changed = q_ini.size() != q_old_ini.size(); } - setToolTip(param_.getSectionDescription(name_).toQString()); + setToolTip(String(param_.getSectionDescription(name_)).toQString()); return changed; } @@ -293,7 +293,7 @@ namespace OpenMS { if (it->tags.count(search_tag)) { - StringList valid_types(it->valid_strings); + StringList valid_types(ListUtils::toStringList(it->valid_strings)); for (Size i = 0; i < valid_types.size(); ++i) { if (!valid_types[i].hasPrefix("*.")) @@ -307,11 +307,11 @@ namespace OpenMS IOInfo io_info; io_info.param_name = it.getName(); io_info.valid_types = valid_types; - if (it->value.valueType() == DataValue::STRING_LIST) + if (it->value.valueType() == ParamValue::STRING_LIST) { io_info.type = IOInfo::IOT_LIST; } - else if (it->value.valueType() == DataValue::STRING_VALUE) + else if (it->value.valueType() == ParamValue::STRING_VALUE) { io_info.type = IOInfo::IOT_FILE; } @@ -549,9 +549,9 @@ namespace OpenMS } else { - if (param_tmp.getValue(param_name).valueType() == DataValue::STRING_LIST) + if (param_tmp.getValue(param_name).valueType() == ParamValue::STRING_LIST) { - param_tmp.setValue(param_name, StringListUtils::fromQStringList(file_list)); + param_tmp.setValue(param_name, ListUtils::create(StringListUtils::fromQStringList(file_list))); } else { @@ -593,9 +593,9 @@ namespace OpenMS } else { - if (param_tmp.getValue(param_name).valueType() == DataValue::STRING_LIST) + if (param_tmp.getValue(param_name).valueType() == ParamValue::STRING_LIST) { - param_tmp.setValue(param_name, StringListUtils::fromQStringList(output_files)); + param_tmp.setValue(param_name, ListUtils::create(StringListUtils::fromQStringList(output_files))); } else { @@ -1235,7 +1235,7 @@ namespace OpenMS void TOPPASToolVertex::writeParam_(const Param& param, const QString& ini_file) { Param save_param; - save_param.setValue(name_ + ":1:toppas_dummy", DataValue("blub")); + save_param.setValue(name_ + ":1:toppas_dummy", "blub"); save_param.insert(name_ + ":1:", param); save_param.remove(name_ + ":1:toppas_dummy"); save_param.setSectionDescription(name_ + ":1", "Instance '1' section for '" + name_ + "'"); diff --git a/src/openms_gui/source/VISUAL/TVIdentificationViewController.cpp b/src/openms_gui/source/VISUAL/TVIdentificationViewController.cpp index 2cd81a310b3..ea34e67289a 100644 --- a/src/openms_gui/source/VISUAL/TVIdentificationViewController.cpp +++ b/src/openms_gui/source/VISUAL/TVIdentificationViewController.cpp @@ -251,7 +251,7 @@ namespace OpenMS Annotation1DCaret* ditem = new Annotation1DCaret(points, QString(), cols[i], - current_layer.param.getValue("peak_color").toQString()); + String(current_layer.param.getValue("peak_color").toString()).toQString()); ditem->setSelected(false); temporary_annotations_.push_back(ditem); // for removal (no ownership) current_layer.getCurrentAnnotations().push_front(ditem); // for visualization (ownership) diff --git a/src/openms_gui/source/VISUAL/TVToolDiscovery.cpp b/src/openms_gui/source/VISUAL/TVToolDiscovery.cpp new file mode 100644 index 00000000000..48cb7663ba7 --- /dev/null +++ b/src/openms_gui/source/VISUAL/TVToolDiscovery.cpp @@ -0,0 +1,120 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: David Voigt $ +// $Authors: David Voigt $ +// -------------------------------------------------------------------------- + +#include +#include +#include +#include +#include + +#include + +namespace OpenMS +{ + + void TVToolDiscovery::loadParams() + { + // tool params are only loaded once by using a immediately evaluated lambda + static bool _ [[maybe_unused]] = [&]() -> bool + { + // Get a map of all tools + const auto &tools = ToolHandler::getTOPPToolList(); + const auto &utils = ToolHandler::getUtilList(); + // Launch threads for loading tool/util params. + for (auto& tool : tools) + { + const std::string name = tool.first; + param_futures_[name] = std::async(std::launch::async, getParamFromIni_, name); + } + for (auto& util : utils) + { + const std::string name = util.first; + param_futures_[name] = std::async(std::launch::async, getParamFromIni_, name); + } + return true; + }(); + } + + void TVToolDiscovery::waitForParams() + { + // Make sure that future results are only waited for and inserted in params_ once + static bool _ [[maybe_unused]] = [&]() -> bool + { + // Make sure threads have been launched before waiting + loadParams(); + // Wait for futures to finish + for (auto&[name, param_future] : param_futures_) + { + while (param_future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) + { + // Keep GUI responsive while waiting + QCoreApplication::processEvents(); + } + // Make future results available in params_ + params_.emplace(name, param_future.get()); + } + return true; + }(); + } + + const std::map &TVToolDiscovery::getToolParams() + { + // Make sure threads have been launched and waited for before accessing results + loadParams(); + waitForParams(); + return params_; + } + + Param TVToolDiscovery::getParamFromIni_(const std::string &tool_name) + { + // Temporary file path and arguments + String path = File::getTemporaryFile(); + String working_dir = path.prefix(path.find_last_of('/')); + QStringList args{"-write_ini", path.toQString()}; + // Start tool/util to write the ini file + String executable = File::findSiblingTOPPExecutable(tool_name); + ExternalProcess proc; + auto return_state = proc.run(executable.toQString(), args, working_dir.toQString(), false, ExternalProcess::IO_MODE::NO_IO); + // Return empty param if writing the ini file failed + Param tool_param; + if (return_state != ExternalProcess::RETURNSTATE::SUCCESS) + { + return tool_param; + } + // Parse ini file to param object and return it + ParamXMLFile paramFile; + paramFile.load((path).c_str(), tool_param); + return tool_param; + } +} diff --git a/src/openms_gui/source/VISUAL/sources.cmake b/src/openms_gui/source/VISUAL/sources.cmake index e44a9dc08c9..7c81284e985 100644 --- a/src/openms_gui/source/VISUAL/sources.cmake +++ b/src/openms_gui/source/VISUAL/sources.cmake @@ -64,6 +64,7 @@ TVDIATreeTabController.cpp TVIdentificationViewController.cpp TVSpectraViewController.cpp TVControllerBase.cpp +TVToolDiscovery.cpp ) ### add path to the filenames diff --git a/src/pyOpenMS/ClassesToWrap.txt b/src/pyOpenMS/ClassesToWrap.txt index 1feece6e6a9..462466cfe1d 100644 --- a/src/pyOpenMS/ClassesToWrap.txt +++ b/src/pyOpenMS/ClassesToWrap.txt @@ -48,7 +48,6 @@ x IDPosteriorErrorProbability.cpp # 300 lines PosteriorErrorProbabilityModel xx IDRipper.cpp # TODO - not yet done on my side, needs hand-wrapping x IDRTCalibration.cpp # 100 lines x InclusionExclusionListCreator.cpp # TODO should we wrap this? 347 lines -x InspectAdapter.cpp # 750 lines ok InternalCalibration.cpp ok MapAlignerIdentification.cpp ok MapAlignerPoseClustering.cpp @@ -199,7 +198,6 @@ x SeedListGenerator - Generates seed lists for feature detection. # needs more Protein/Peptide Identification ok CompNovo - Performs a peptide/protein identification with the CompNovo engine. -x InspectAdapter - Identifies MS/MS spectra using Inspect (external). x MascotAdapter - Identifies MS/MS spectra using Mascot (external). x MascotAdapterOnline - Identifies MS/MS spectra using Mascot (external). x OMSSAAdapter - Identifies MS/MS spectra using OMSSA (external). diff --git a/src/pyOpenMS/converters/__init__.py b/src/pyOpenMS/converters/__init__.py index 72a214fffbd..a3d85e45770 100644 --- a/src/pyOpenMS/converters/__init__.py +++ b/src/pyOpenMS/converters/__init__.py @@ -12,5 +12,6 @@ def register_converters(): special_converters.append(OpenMSMapConverter()) special_converters.append(CVTermMapConverter()) special_converters.append(OpenMSDataValue()) + special_converters.append(OpenMSParamValue()) special_converters.append(OpenMSDPosition2()) special_converters.append(OpenMSDPosition2Vector()) diff --git a/src/pyOpenMS/converters/special_autowrap_conversionproviders.py b/src/pyOpenMS/converters/special_autowrap_conversionproviders.py index e17ac9086ba..1b00aba7bfb 100644 --- a/src/pyOpenMS/converters/special_autowrap_conversionproviders.py +++ b/src/pyOpenMS/converters/special_autowrap_conversionproviders.py @@ -158,6 +158,50 @@ def output_conversion(self, cpp_type, input_cpp_var, output_py_var): | raise Exception("DataValue instance has invalid value type %d" % _type) """, locals()) +class OpenMSParamValue(TypeConverterBase): + + def get_base_types(self): + return "ParamValue", + + def matches(self, cpp_type): + return not cpp_type.is_ptr and not cpp_type.is_ref + + def matching_python_type(self, cpp_type): + return "" + + def type_check_expression(self, cpp_type, argument_var): + return "isinstance(%s, (int, long, float, list, bytes, str, unicode))" % argument_var + + def input_conversion(self, cpp_type, argument_var, arg_num): + call_as = "deref(ParamValue(%s).inst.get())" % argument_var + return "", call_as, "" + + def output_conversion(self, cpp_type, input_cpp_var, output_py_var): + # this one is slow as it uses construction of python type ParamValue for + # delegating conversion to this type, which reduces code below: + return Code().add(""" + |cdef ParamValue _value = ParamValue.__new__(ParamValue) + |_value.inst = shared_ptr[_ParamValue](new _ParamValue($input_cpp_var)) + |cdef int _type = $input_cpp_var.valueType() + |cdef object $output_py_var + |if _type == ValueType.STRING_VALUE: + | $output_py_var = _value.toString() + |elif _type == ValueType.INT_VALUE: + | $output_py_var = _value.toInt() + |elif _type == ValueType.DOUBLE_VALUE: + | $output_py_var = _value.toDouble() + |elif _type == ValueType.INT_LIST: + | $output_py_var = _value.toIntVector() + |elif _type == ValueType.DOUBLE_LIST: + | $output_py_var = _value.toDoubleVector() + |elif _type == ValueType.STRING_LIST: + | $output_py_var = _value.toStringVector() + |elif _type == ValueType.EMPTY_VALUE: + | $output_py_var = None + |else: + | raise Exception("ParamValue instance has invalid value type %d" % _type) + """, locals()) + class OpenMSStringConverter(TypeConverterBase): diff --git a/src/pyOpenMS/pxds/Acquisition.pxd b/src/pyOpenMS/pxds/Acquisition.pxd index 5460ad393c3..3635364b778 100644 --- a/src/pyOpenMS/pxds/Acquisition.pxd +++ b/src/pyOpenMS/pxds/Acquisition.pxd @@ -1,7 +1,6 @@ from libcpp cimport bool from MetaInfoInterface cimport * from libcpp.vector cimport vector as libcpp_vector -from DataValue cimport * from String cimport * cdef extern from "" namespace "OpenMS": diff --git a/src/pyOpenMS/pxds/BinnedSpectrum.pxd b/src/pyOpenMS/pxds/BinnedSpectrum.pxd index 07779cbad32..44651d3df84 100644 --- a/src/pyOpenMS/pxds/BinnedSpectrum.pxd +++ b/src/pyOpenMS/pxds/BinnedSpectrum.pxd @@ -1,5 +1,4 @@ from libcpp.vector cimport vector as libcpp_vector -from libcpp.string cimport string as libcpp_string from Types cimport * from libcpp cimport bool from MSSpectrum cimport * diff --git a/src/pyOpenMS/pxds/ConfidenceScoring.pxd b/src/pyOpenMS/pxds/ConfidenceScoring.pxd index 9843225cdfe..a3e2fa22ccc 100644 --- a/src/pyOpenMS/pxds/ConfidenceScoring.pxd +++ b/src/pyOpenMS/pxds/ConfidenceScoring.pxd @@ -1,5 +1,4 @@ from libcpp.vector cimport vector as libcpp_vector -from libcpp.string cimport string as libcpp_string from FeatureMap cimport * from TargetedExperiment cimport * from TransformationDescription cimport * diff --git a/src/pyOpenMS/pxds/DataValue.pxd b/src/pyOpenMS/pxds/DataValue.pxd index 7816dc1b92c..7010926e5d8 100644 --- a/src/pyOpenMS/pxds/DataValue.pxd +++ b/src/pyOpenMS/pxds/DataValue.pxd @@ -1,5 +1,5 @@ -from libcpp.string cimport string as libcpp_string from libcpp.vector cimport vector as libcpp_vector +from ParamValue cimport * from String cimport * from StringList cimport * from IntList cimport * @@ -17,9 +17,10 @@ cdef extern from "" namespace "OpenMS": DataValue(StringList) nogil except + DataValue(IntList) nogil except + DataValue(DoubleList) nogil except + + DataValue(ParamValue) nogil except + #conversion ops, different declarations as in c++ ! - int operator()(int) nogil except + #wrap-cast:toInt + int operator()(DataValue) nogil except + #wrap-cast:toInt String operator()(DataValue) nogil except + #wrap-cast:toString double operator()(DataValue) nogil except + #wrap-cast:toDouble StringList toStringList() nogil except + diff --git a/src/pyOpenMS/pxds/Feature.pxd b/src/pyOpenMS/pxds/Feature.pxd index 590167d4200..278375fda65 100644 --- a/src/pyOpenMS/pxds/Feature.pxd +++ b/src/pyOpenMS/pxds/Feature.pxd @@ -1,6 +1,5 @@ from libcpp cimport bool from libcpp.vector cimport vector as libcpp_vector -from DataValue cimport * from ConvexHull2D cimport * from PeptideIdentification cimport * from BaseFeature cimport * diff --git a/src/pyOpenMS/pxds/ISpectrumAccess.pxd b/src/pyOpenMS/pxds/ISpectrumAccess.pxd index 9b9119539c3..05013487761 100644 --- a/src/pyOpenMS/pxds/ISpectrumAccess.pxd +++ b/src/pyOpenMS/pxds/ISpectrumAccess.pxd @@ -1,6 +1,6 @@ from Types cimport * from smart_ptr cimport shared_ptr -from libcpp.string cimport string as libcpp_string +from libcpp.string cimport string as libcpp_utf8_output_string from libcpp.vector cimport vector as libcpp_vector from OpenSwathDataStructures cimport * @@ -25,5 +25,5 @@ cdef extern from "" namespace shared_ptr[OSChromatogram] getChromatogramById(int id_) nogil except + size_t getNrChromatograms() nogil except + - libcpp_string getChromatogramNativeID(int id_) nogil except + + libcpp_utf8_output_string getChromatogramNativeID(int id_) nogil except + diff --git a/src/pyOpenMS/pxds/MRMTransitionGroup.pxd b/src/pyOpenMS/pxds/MRMTransitionGroup.pxd index 4d0f5716e8d..83881a07d83 100644 --- a/src/pyOpenMS/pxds/MRMTransitionGroup.pxd +++ b/src/pyOpenMS/pxds/MRMTransitionGroup.pxd @@ -1,5 +1,5 @@ from libcpp.vector cimport vector as libcpp_vector -from libcpp.string cimport string as libcpp_string +from libcpp.string cimport string as libcpp_utf8_string # triggers input conversion provider from MRMFeature cimport * from ReactionMonitoringTransition cimport * from LightTargetedExperiment cimport * @@ -46,7 +46,7 @@ cdef extern from "" namespace "OpenMS": MRMFeature getBestFeature() nogil except + void getLibraryIntensity(libcpp_vector[double] result) nogil except+ - MRMTransitionGroup[SpectrumT, TransitionT] subset(libcpp_vector[ libcpp_string ] tr_ids) nogil except + + MRMTransitionGroup[SpectrumT, TransitionT] subset(libcpp_vector[ libcpp_utf8_string ] tr_ids) nogil except + bool isInternallyConsistent() nogil except + diff --git a/src/pyOpenMS/pxds/MSSpectrum.pxd b/src/pyOpenMS/pxds/MSSpectrum.pxd index 63ce123edc3..1d3c9abb314 100644 --- a/src/pyOpenMS/pxds/MSSpectrum.pxd +++ b/src/pyOpenMS/pxds/MSSpectrum.pxd @@ -1,5 +1,4 @@ from libcpp.vector cimport vector as libcpp_vector -from libcpp.string cimport string as libcpp_string from Peak1D cimport * from String cimport * from RangeManager cimport * diff --git a/src/pyOpenMS/pxds/OPXLHelper.pxd b/src/pyOpenMS/pxds/OPXLHelper.pxd index e8106a1dfca..04c2d6a2bbf 100644 --- a/src/pyOpenMS/pxds/OPXLHelper.pxd +++ b/src/pyOpenMS/pxds/OPXLHelper.pxd @@ -2,7 +2,7 @@ from Types cimport * from libcpp.vector cimport vector as libcpp_vector from libcpp.pair cimport pair as libcpp_pair from libcpp cimport bool -from libcpp.string cimport string as libcpp_string +from libcpp.string cimport string as libcpp_utf8_string from XLPrecursor cimport * from AASeqWithMass cimport * from DoubleList cimport * @@ -99,7 +99,7 @@ cdef extern from "" namespace "OpenMS": StringList cross_link_residue2, String cross_link_name, bool use_sequence_tags, - const libcpp_vector[ libcpp_string ]& tags) nogil except + + const libcpp_vector[ libcpp_utf8_string ]& tags) nogil except + double computePrecursorError(CrossLinkSpectrumMatch csm, double precursor_mz, int precursor_charge) nogil except + diff --git a/src/pyOpenMS/pxds/OSWFile.pxd b/src/pyOpenMS/pxds/OSWFile.pxd index 61c934e9dbd..e1cbc0b1526 100644 --- a/src/pyOpenMS/pxds/OSWFile.pxd +++ b/src/pyOpenMS/pxds/OSWFile.pxd @@ -1,13 +1,13 @@ from Types cimport * from libcpp.map cimport map as libcpp_map -from libcpp.string cimport string as libcpp_string +from libcpp.string cimport string as libcpp_utf8_string from libcpp.vector cimport vector as libcpp_vector from String cimport * cdef extern from "" namespace "OpenMS": cdef cppclass OSWFile "OpenMS::OSWFile": - OSWFile(const libcpp_string filename) nogil except + + OSWFile(const libcpp_utf8_string filename) nogil except + OSWFile(OSWFile) nogil except + #wrap-ignore # Cannot wrap libcpp_ostream diff --git a/src/pyOpenMS/pxds/Param.pxd b/src/pyOpenMS/pxds/Param.pxd index e124a3e1beb..333fc44cf27 100644 --- a/src/pyOpenMS/pxds/Param.pxd +++ b/src/pyOpenMS/pxds/Param.pxd @@ -1,10 +1,10 @@ +from libcpp.string cimport string as libcpp_utf8_string from Types cimport * -from DataValue cimport * -from String cimport * -from StringList cimport * +from ParamValue cimport * from ParamNode cimport * from ParamEntry cimport * + # this class has addons, see the ./addons folder cdef extern from "" namespace "OpenMS": @@ -27,34 +27,36 @@ cdef extern from "" namespace "OpenMS": Param(Param) nogil except + bool operator==(Param) nogil except + - void setValue(String key, DataValue val, String desc, StringList tags) nogil except + - void setValue(String key, DataValue val, String desc) nogil except + - void setValue(String key, DataValue val) nogil except + - DataValue getValue(String key) nogil except + - ParamEntry getEntry(String) nogil except + - bool exists(String key) nogil except + + void setValue(libcpp_utf8_string key, ParamValue val, libcpp_utf8_string desc, libcpp_vector[libcpp_utf8_string] tags) nogil except + + void setValue(libcpp_utf8_string key, ParamValue val, libcpp_utf8_string desc) nogil except + + void setValue(libcpp_utf8_string key, ParamValue val) nogil except + + ParamValue getValue(libcpp_utf8_string key) nogil except + + ValueType getValueType(libcpp_utf8_string key) nogil except + + + ParamEntry getEntry(libcpp_utf8_string) nogil except + + bool exists(libcpp_utf8_string key) nogil except + - void addTag(String key, String tag) nogil except + - void addTags(String key, StringList tags) nogil except + - int hasTag(String key, String tag) nogil except + - StringList getTags(String key) nogil except + - void clearTags(String key) nogil except + + void addTag(libcpp_utf8_string key, libcpp_utf8_string tag) nogil except + + void addTags(libcpp_utf8_string key, libcpp_vector[libcpp_utf8_string] tags) nogil except + + int hasTag(libcpp_utf8_string key, libcpp_utf8_string tag) nogil except + + libcpp_vector[libcpp_utf8_string] getTags(libcpp_utf8_string key) nogil except + + void clearTags(libcpp_utf8_string key) nogil except + - String getDescription(String key) nogil except + - void setSectionDescription(String key, String desc) nogil except + - String getSectionDescription(String key) nogil except + + libcpp_utf8_output_string getDescription(libcpp_utf8_string key) nogil except + + void setSectionDescription(libcpp_utf8_string key, libcpp_utf8_string desc) nogil except + + libcpp_utf8_output_string getSectionDescription(libcpp_utf8_string key) nogil except + Size size() nogil except + bool empty() nogil except + void clear() nogil except + - void insert(String prefix, Param param) nogil except + + void insert(libcpp_utf8_string prefix, Param param) nogil except + - void remove(String key) nogil except + - void removeAll(String prefix) nogil except + + void remove(libcpp_utf8_string key) nogil except + + void removeAll(libcpp_utf8_string prefix) nogil except + - Param copy(String prefix, bool) nogil except + - Param copy(String prefix) nogil except + + Param copy(libcpp_utf8_string prefix, bool) nogil except + + Param copy(libcpp_utf8_string prefix) nogil except + # wrapped manually for overloading with dict parameter: bool update(Param p_old, bool add_unknow) nogil except + # wrap-ignore @@ -62,18 +64,18 @@ cdef extern from "" namespace "OpenMS": void merge(Param toMerge) nogil except + - void setDefaults(Param defaults, String previx, bool showMessage) nogil except + - void setDefaults(Param defaults, String previx) nogil except + + void setDefaults(Param defaults, libcpp_utf8_string prefix, bool showMessage) nogil except + + void setDefaults(Param defaults, libcpp_utf8_string prefix) nogil except + void setDefaults(Param defaults) nogil except + - void checkDefaults(String name, Param defaults, String prefix) nogil except + - void checkDefaults(String name, Param defaults) nogil except + + void checkDefaults(libcpp_utf8_string name, Param defaults, libcpp_utf8_string prefix) nogil except + + void checkDefaults(libcpp_utf8_string name, Param defaults) nogil except + - void setValidStrings(String key, libcpp_vector[String] strings) nogil except + - void setMinInt(String key, int min) nogil except + - void setMaxInt(String key, int max) nogil except + - void setMinFloat(String key, double min) nogil except + - void setMaxFloat(String key, double max) nogil except + + void setValidStrings(libcpp_utf8_string key, libcpp_vector[libcpp_utf8_string] strings) nogil except + + void setMinInt(libcpp_utf8_string key, int min) nogil except + + void setMaxInt(libcpp_utf8_string key, int max) nogil except + + void setMinFloat(libcpp_utf8_string key, double min) nogil except + + void setMaxFloat(libcpp_utf8_string key, double max) nogil except + #void parseCommandLine(int argc, char ** argv, String prefix) # wrap-ignore #void parseCommandLine(int argc, char ** argv) # wrap-ignore @@ -88,7 +90,7 @@ cdef extern from "" namespace "OpenMS::Param": # no-pxd-import ParamIterator operator++() nogil except + ParamIterator operator--() nogil except + - String getName() nogil except + + libcpp_utf8_string getName() nogil except + int operator==(ParamIterator) nogil except + int operator!=(ParamIterator) nogil except + int operator<(ParamIterator) nogil except + @@ -103,12 +105,12 @@ cdef extern from "" namespace "OpenMS::Param::Par cdef cppclass TraceInfo: - TraceInfo(String n, String d, bool o) nogil except + + TraceInfo(libcpp_utf8_string n, libcpp_utf8_string d, bool o) nogil except + TraceInfo(TraceInfo) nogil except + # name of the node - String name + libcpp_string name # description of the node - String description + libcpp_string description # If it was opened (true) or closed (false) bool opened diff --git a/src/pyOpenMS/pxds/ParamEntry.pxd b/src/pyOpenMS/pxds/ParamEntry.pxd index fd4ad1cfb83..59362d9f9b6 100644 --- a/src/pyOpenMS/pxds/ParamEntry.pxd +++ b/src/pyOpenMS/pxds/ParamEntry.pxd @@ -1,21 +1,18 @@ +from Types cimport * from libcpp.string cimport string as libcpp_string from libcpp.vector cimport vector as libcpp_vector from libcpp.set cimport set as libcpp_set -from libcpp cimport bool -from DataValue cimport * -from String cimport * -from StringList cimport * -from ParamNode cimport * +from ParamValue cimport * cdef extern from "" namespace "OpenMS::Param": cdef cppclass ParamEntry: - String name - String description - DataValue value - libcpp_set[String] tags - libcpp_vector[String] valid_strings + libcpp_string name + libcpp_string description + ParamValue value + libcpp_set[libcpp_string] tags + libcpp_vector[libcpp_string] valid_strings double max_float double min_float Int max_int @@ -23,9 +20,9 @@ cdef extern from "" namespace "OpenMS::Param": ParamEntry() nogil except + ParamEntry(ParamEntry) nogil except + - ParamEntry(String n, DataValue v, String d, StringList t) nogil except + - ParamEntry(String n, DataValue v, String d) nogil except + + ParamEntry(libcpp_string n, ParamValue v, libcpp_string d, libcpp_vector[libcpp_string] t) nogil except + + ParamEntry(libcpp_string n, ParamValue v, libcpp_string d) nogil except + - bool isValid(String &message) nogil except + + # TODO: wrap bool isValid(libcpp_string & message) maybe as libcpp_pair[bool, libcpp_str] isValid() if possible bool operator==(ParamEntry) nogil except + diff --git a/src/pyOpenMS/pxds/ParamNode.pxd b/src/pyOpenMS/pxds/ParamNode.pxd index 38dbb8d05a2..437b1def774 100644 --- a/src/pyOpenMS/pxds/ParamNode.pxd +++ b/src/pyOpenMS/pxds/ParamNode.pxd @@ -1,7 +1,7 @@ from Types cimport * from libcpp cimport bool from Types cimport * -from DataValue cimport * +from ParamValue cimport * from String cimport * from Map cimport * from ParamEntry cimport * diff --git a/src/pyOpenMS/pxds/ParamValue.pxd b/src/pyOpenMS/pxds/ParamValue.pxd new file mode 100644 index 00000000000..cdff8a0621f --- /dev/null +++ b/src/pyOpenMS/pxds/ParamValue.pxd @@ -0,0 +1,42 @@ +from libcpp cimport bool +from libcpp.string cimport string as libcpp_utf8_string # triggers input conversion provider for std string +from libcpp.string cimport string as libcpp_utf8_output_string #triggers output conversion provider for std string +from libcpp.vector cimport vector as libcpp_vector + +cdef extern from "" namespace "OpenMS": + + cdef cppclass ParamValue: + ParamValue() nogil except + + ParamValue(ParamValue) nogil except + # wrap-ignore + ParamValue(char *) nogil except + + ParamValue(const libcpp_utf8_string&) nogil except + + ParamValue(int) nogil except + + ParamValue(double) nogil except + + ParamValue(libcpp_vector[ libcpp_utf8_string ]) nogil except + + ParamValue(libcpp_vector[ int ]) nogil except + + ParamValue(libcpp_vector[ double ]) nogil except + + + #conversion ops, different declarations as in c++ ! + int operator()(ParamValue) nogil except + #wrap-cast:toInt + libcpp_utf8_output_string operator()(ParamValue) nogil except + #wrap-cast:toString + double operator()(ParamValue) nogil except + #wrap-cast:toDouble + libcpp_vector[ libcpp_utf8_string ] toStringVector() nogil except + + libcpp_vector[ double ] toDoubleVector() nogil except + + libcpp_vector[ int ] toIntVector() nogil except + + bool toBool() nogil except + + + ValueType valueType() nogil except + + + int isEmpty() nogil except + + +cdef extern from "" namespace "OpenMS::ParamValue": + + cdef enum ValueType "OpenMS::ParamValue::ValueType": + STRING_VALUE # string value + INT_VALUE # integer value + DOUBLE_VALUE # double value + STRING_LIST # string list + INT_LIST # integer list + DOUBLE_LIST # double list + EMPTY_VALUE # empty value + diff --git a/src/pyOpenMS/pxds/PrecursorCorrection.pxd b/src/pyOpenMS/pxds/PrecursorCorrection.pxd index a8fbd7b4f52..308c17ad9c0 100644 --- a/src/pyOpenMS/pxds/PrecursorCorrection.pxd +++ b/src/pyOpenMS/pxds/PrecursorCorrection.pxd @@ -13,38 +13,18 @@ cdef extern from "" namespac cdef cppclass PrecursorCorrection: - void getPrecursors(MSExperiment & exp, - libcpp_vector[ Precursor ] & precursors, - libcpp_vector[ double ] & precursors_rt, - libcpp_vector[ size_t ] & precursor_scan_index) nogil except + - - void writeHist(String & out_csv, - libcpp_vector[ double ] & delta_mzs, - libcpp_vector[ double ] & mzs, - libcpp_vector[ double ] & rts) nogil except + - - libcpp_set[ size_t ] correctToNearestMS1Peak(MSExperiment & exp, - double mz_tolerance, - bool ppm, - libcpp_vector[ double ] & delta_mzs, - libcpp_vector[ double ] & mzs, - libcpp_vector[ double ] & rts) nogil except + - - libcpp_set[ size_t ] correctToHighestIntensityMS1Peak(MSExperiment & exp, - double mz_tolerance, - bool ppm, - libcpp_vector[ double ] & delta_mzs, - libcpp_vector[ double ] & mzs, - libcpp_vector[ double ] & rts) nogil except + - - libcpp_set[ size_t ] correctToNearestFeature(FeatureMap & features, - MSExperiment & exp, - double rt_tolerance_s, - double mz_tolerance, - bool ppm, - bool believe_charge, - bool keep_original, - bool all_matching_features, - int max_trace, - int debug_level) nogil except + + PrecursorCorrection() nogil except + + +# COMMENT: wrap static methods +cdef extern from "" namespace "OpenMS::PrecursorCorrection": + + void getPrecursors(MSExperiment & exp, libcpp_vector[ Precursor ] & precursors, libcpp_vector[ double ] & precursors_rt, libcpp_vector[ size_t ] & precursor_scan_index) nogil except + # wrap-attach:PrecursorCorrection + + void writeHist(String & out_csv, libcpp_vector[ double ] & delta_mzs, libcpp_vector[ double ] & mzs, libcpp_vector[ double ] & rts) nogil except + # wrap-attach:PrecursorCorrection + + libcpp_set[ size_t ] correctToNearestMS1Peak(MSExperiment & exp, double mz_tolerance, bool ppm, libcpp_vector[ double ] & delta_mzs, libcpp_vector[ double ] & mzs, libcpp_vector[ double ] & rts) nogil except + # wrap-attach:PrecursorCorrection + + libcpp_set[ size_t ] correctToHighestIntensityMS1Peak(MSExperiment & exp, double mz_tolerance, bool ppm, libcpp_vector[ double ] & delta_mzs, libcpp_vector[ double ] & mzs, libcpp_vector[ double ] & rts) nogil except + # wrap-attach:PrecursorCorrection + + libcpp_set[ size_t ] correctToNearestFeature(FeatureMap & features, MSExperiment & exp, double rt_tolerance_s, double mz_tolerance, bool ppm, bool believe_charge, bool keep_original, bool all_matching_features, int max_trace, int debug_level) nogil except + # wrap-attach:PrecursorCorrection diff --git a/src/pyOpenMS/pxds/Tagger.pxd b/src/pyOpenMS/pxds/Tagger.pxd index ac533034072..b5498845722 100644 --- a/src/pyOpenMS/pxds/Tagger.pxd +++ b/src/pyOpenMS/pxds/Tagger.pxd @@ -1,6 +1,6 @@ from Types cimport * from libcpp.vector cimport vector as libcpp_vector -from libcpp.string cimport string as libcpp_string +from libcpp.string cimport string as libcpp_utf8_string # triggers input conversion provider from StringList cimport * from MSSpectrum cimport * @@ -20,9 +20,9 @@ cdef extern from "" namespace "OpenMS": const StringList& var_mods) nogil except + void getTag(const libcpp_vector[ double ]& mzs, - libcpp_vector[ libcpp_string ]& tags) nogil except + + libcpp_vector[ libcpp_utf8_string ]& tags) nogil except + void getTag(const MSSpectrum& spec, - libcpp_vector[ libcpp_string ]& tags) nogil except + + libcpp_vector[ libcpp_utf8_string ]& tags) nogil except + void setMaxCharge(size_t max_charge) nogil except + diff --git a/src/pyOpenMS/pyTOPP/CTDsupport.py b/src/pyOpenMS/pyTOPP/CTDsupport.py new file mode 100644 index 00000000000..3859e58649d --- /dev/null +++ b/src/pyOpenMS/pyTOPP/CTDsupport.py @@ -0,0 +1,89 @@ +import CTDopts +import sys +import os +from CTDopts.CTDopts import CTDModel, parse_cl_directives +import pyopenms as pms +import tempfile + + +# code related to CTD support +def addParamToCTDopts(defaults, model): + keys = defaults.keys() + for key in keys: + ctd_tags = defaults.getTags(key) + value = defaults.getValue(key) + desc = defaults.getDescription(key) + + ctd_required = False + if "required" in ctd_tags: + ctd_required = True + + ctd_type = None + ctd_type_str = '' + ctd_list = False + + if isinstance(value, int): + ctd_type = int + ctd_type_str = 'int' + elif isinstance(value, float): + ctd_type = float + ctd_type_str = 'float' + elif isinstance(value, str): + ctd_type = str + ctd_type_str = 'str' + elif isinstance(value, list): + ctd_list = True + # we can't determine the type based on an element so we need this helper function + value_type = defaults.getValueType(key) + if value_type == pms.ValueType.STRING_LIST: + ctd_type=str + ctd_type_str = 'list of str' + elif value_type == pms.ValueType.DOUBLE_LIST: + ctd_type=float + ctd_type_str = 'list of float' + elif value_type == pms.ValueType.INT_LIST: + ctd_type=int + ctd_type_str = 'list of int' + + print('Adding parameter: {0} with value: {1} and description: "{2}".'.format(key, value, desc)) + print(' required: {0} \t tags: {1} \t type: {2}.'.format(ctd_required, ctd_tags, ctd_type_str)) + + model.add( + key.decode(), + required=ctd_required, + type=ctd_type, + default=value, + is_list=ctd_list, + description=desc) + + +def parseCTDCommandLine(argv, model, openms_param): + # Configure CTDOpt to use OpenMS style on the command line. + directives = parse_cl_directives(argv, input_ctd='ini', write_tool_ctd='write_ini', prefix='-') + + if directives["write_tool_ctd"] is not None: # triggered if -write_ini was provided on CML + # if called with -write_ini write CTD + model.write_ctd(directives["write_tool_ctd"]) + exit(0) + elif directives["input_ctd"] is not None: # read ctd/ini file + model = CTDModel(from_file=directives["input_ctd"]) +# print(model.get_defaults()) + + param = pms.Param() + fh = pms.ParamXMLFile() + fh.load(directives["input_ctd"], param) + openms_param.update(param, True) + return model.get_defaults(), openms_param + + else: # only command line options provided + temp = tempfile.NamedTemporaryFile(suffix='ini') # makes sure we get a writable file + tmp_name = temp.name + temp.close() # removes the file + + model.write_ctd(tmp_name) + param = pms.Param() + fh = pms.ParamXMLFile() + fh.load(tmp_name, param) + openms_param.update(param) + os.remove(tmp_name) + return model.parse_cl_args(argv), openms_param diff --git a/src/pyOpenMS/pyTOPP/common.py b/src/pyOpenMS/pyTOPP/common.py index 70a8aa2c84b..72e09c61e74 100644 --- a/src/pyOpenMS/pyTOPP/common.py +++ b/src/pyOpenMS/pyTOPP/common.py @@ -21,10 +21,10 @@ def _addDataProcessing(item, params, action): sw.setName(os.path.basename(sys.argv[0])) sw.setVersion(pms.VersionInfo.getVersion()) p.setSoftware(sw) - p.setCompletionTime(pms.DateTime.now()) + p.setCompletionTime(pms.DateTime.now()) # TODO: check if this is the reason for the many data processing entries for k, v in params.asDict().items(): - p.setMetaValue("parameter: "+k, v) + p.setMetaValue(b"parameter: "+k, v) dp.append(p) item.setDataProcessing(dp) diff --git a/src/pyOpenMS/pyTOPP/pyTOPPExample.py b/src/pyOpenMS/pyTOPP/pyTOPPExample.py new file mode 100644 index 00000000000..70a82305b1e --- /dev/null +++ b/src/pyOpenMS/pyTOPP/pyTOPPExample.py @@ -0,0 +1,71 @@ +import CTDopts +import sys +from CTDopts.CTDopts import CTDModel, parse_cl_directives +import pyopenms as pms +import logging +from common import addDataProcessing +from CTDsupport import * + + +def main(): + + # register command line arguments + model = CTDModel( + name='NameOfThePyTOPPTool', # required + version='1.0', # required + description='This is an example tool how to write pyTOPP tools compatible with the OpenMS workflow ecosystem.', + manual='RTF', + docurl='http://dummy.url/docurl.html', + category='Example', + executableName='exampletool', + executablePath='/path/to/exec/exampletool-1.0/exampletool' + ) + + # Register in / out etc. with CTDModel + model.add( + 'input', + required=True, + type='input-file', + is_list=False, + file_formats=['mzML'], # filename restrictions + description='Input file' + ) + + model.add( + 'output', + required=True, + type='output-file', + is_list=False, + file_formats=['mzML'], # filename restrictions + description='Output file' + ) + + defaults = pms.PeakPickerHiRes().getDefaults() + + # expose algorithm parameters in command line options + addParamToCTDopts(defaults, model) + + # parse command line + # if -write_ini is provided, store model in CTD file, exit with error code 0 + # if -ini is provided, load CTD file into defaults Param object and return new model with paraneters set as defaults + arg_dict, openms_params = parseCTDCommandLine(sys.argv, model, defaults); + + # data processing + fh = pms.MzMLFile() + fh.setLogType(pms.LogType.CMD) + input_map = pms.MSExperiment() + + fh.load(arg_dict["input"], input_map) + + pp = pms.PeakPickerHiRes() + pp.setParameters(openms_params) + out_map = pms.MSExperiment() + pp.pickExperiment(input_map, out_map) + + out_map = addDataProcessing(out_map, openms_params, pms.ProcessingAction.PEAK_PICKING) + fh = pms.FileHandler() + fh.storeExperiment(arg_dict["output"], out_map) + +if __name__ == "__main__": + main() + diff --git a/src/pyOpenMS/tests/integration_tests/test_MRMRTNormalizer.py b/src/pyOpenMS/tests/integration_tests/test_MRMRTNormalizer.py index 526ef4663fa..b712699f6de 100644 --- a/src/pyOpenMS/tests/integration_tests/test_MRMRTNormalizer.py +++ b/src/pyOpenMS/tests/integration_tests/test_MRMRTNormalizer.py @@ -54,7 +54,7 @@ def test_run_mrmrtnormalizer(self): featurefinder = pyopenms.MRMFeatureFinderScoring() # set the correct rt use values scoring_params = pyopenms.MRMFeatureFinderScoring().getDefaults(); - scoring_params.setValue("Scores:use_rt_score".encode(), 'false'.encode(), ''.encode()) + scoring_params.setValue(b"Scores:use_rt_score", b'false', b'') featurefinder.setParameters(scoring_params); featurefinder.pickExperiment(chromatograms, output, targeted, trafo, empty_swath) diff --git a/src/pyOpenMS/tests/unittests/testSpecialCases.py b/src/pyOpenMS/tests/unittests/testSpecialCases.py index d133ffddd96..876f0eed8ca 100644 --- a/src/pyOpenMS/tests/unittests/testSpecialCases.py +++ b/src/pyOpenMS/tests/unittests/testSpecialCases.py @@ -30,16 +30,6 @@ def testContainers(): _test_container(pyopenms.MSExperiment, pyopenms.MSSpectrum, "addSpectrum") _test_container(pyopenms.FeatureMap, pyopenms.Feature) - -def testParamEntry(): - # as ParamEntry::isValid takes "String &" as input argument, which - # can not be implemened by a Python string, here no automatic - # conversion from a basestring should happen: - p = pyopenms.ParamEntry() - message = pyopenms.String() - assert p.isValid(message) - assert message.c_str() == b"" - def testConvexHull2D(): h = pyopenms.ConvexHull2D() diff --git a/src/superhirn/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmSH.cpp b/src/superhirn/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmSH.cpp index de9be3ef478..e88ab196c16 100644 --- a/src/superhirn/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmSH.cpp +++ b/src/superhirn/source/TRANSFORMATIONS/FEATUREFINDER/FeatureFinderAlgorithmSH.cpp @@ -45,7 +45,7 @@ namespace OpenMS { // ---------------------------------------------------------------------------------------------------- this->defaults_.setValue("centroiding:active", "false", "MS1 data centroid data"); - this->defaults_.setValidStrings("centroiding:active", ListUtils::create("true,false")); + this->defaults_.setValidStrings("centroiding:active", {"true","false"}); // ---------------------------------------------------------------------------------------------------- this->defaults_.setValue("ms1:precursor_detection_scan_levels", ListUtils::create("1"), "Precursor detection scan levels"); // ---------------------------------------------------------------------------------------------------- @@ -92,7 +92,7 @@ namespace OpenMS this->defaults_.setMinFloat("ms1:mz_tolerance", 0.0); // ---------------------------------------------------------------------------------------------------- this->defaults_.setValue("ms1_feature_merger:active", "true", "Activation of MS1 feature merging post processing"); - this->defaults_.setValidStrings("ms1_feature_merger:active", ListUtils::create("true,false")); + this->defaults_.setValidStrings("ms1_feature_merger:active", {"true","false"}); // ---------------------------------------------------------------------------------------------------- this->defaults_.setValue("ms1_feature_merger:tr_resolution", 0.01, "MS1 LC retention time resolution"); this->defaults_.setMinFloat("ms1_feature_merger:tr_resolution", 0.0); diff --git a/src/tests/class_tests/openms/data/IM_FAIMS_test.mzML b/src/tests/class_tests/openms/data/IM_FAIMS_test.mzML new file mode 100755 index 00000000000..6c133477511 --- /dev/null +++ b/src/tests/class_tests/openms/data/IM_FAIMS_test.mzML @@ -0,0 +1,1065 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eJwc13c81d8fB3BZZSVSmSlkhC8iMvtkFTKyi4ZkpIXGxUV2dkRmiEjJplCkKNkjykoysrcQkt+r31/Px+fez/18znmf9/t9ztVYYJ3SkiERvVnCJYaQ1lrNxwJG8lh77nIhEa6n9zruhWaF362EoL9wI+NZ6Lm43hEEmZ6v1jyAH8h/ShNhVTm9CuFGIsbYqaS04PIDCgFDqPeKGPKE0Rp3gipgg/Rd7QlYXN+lvAhb78pJ/YFMPTtS1XxIhIpfctxJ+FVfKsIEJrUznQuBDyUyxd7DFWYBxp/wxa7t1DOQQXljfRnyBMwvbkL9aapGMV8S8eixVNgt6Hzvy/U4eE9K0C4VPtwgn8+CM3yd36aCSURo5+nuJWhWMPDlL6zrdn8vE0IibsfuLrCCqZLfchzgf7NPs25CdQbB1HDoeZ4mORaKd48nPIaNsnnhH+DvfdS+Y/DO1G6veRjZ95/HGmzL4O18F04i7ge1f6mDwtGhHZ+hnVp6yzKM6NZq4LxPIsJUper5Ychnnjox+COnsaAlEuPfJAq74HnX14UDkEHW7uX2BySiSzmlVBF2OJ8qU4dSrdte68JFk4+vTSEP9b0352FRj265PQx28Hj3EJ74eeRjFQx1PVLTAK/IKn/qgNsPmtaNwO4LDvWz0OCdb8NvKEdh0HYgikRs8z3WbQHLG+J6LkED5aXea/+/5hiUisX8vzz5qQCr6KXH1aBb5Ml1R8hd+OJnJsy/8E1yFr6a/CzzGyamNh/ZEkcijt9rEe6PJxEa5wfFx+DGxbVD8/CSUPjxXQkkwufPBytVePLVDjsduJ5oddUYRuWUOJ2FeyZZSbbwxkpa7CN41WYs5x3kuedeVAcnOnaVfYbq3G6tTo9IRGw0bacbrJGP6/OFkZ+u07yGsmLFipRJyKMzSVePQc7vj29q//P+czcjqPHh8qPmVBJheJ/uaSeMDsrN+wHlj6+O704jEaaiU/+ZwmuR/Q6hcFVl6tZDyMT91zMZir5m387zhERQX3RhF4Rp8n18EtBHOtPKBkqruaQmQv2gfdnp8PJm06sc+Ep7gI8rk0RoXwmREICXKhSUxOHK6+pA63+G/J59ARWzPVQGISVrgs4kfPb8jfkvuGcow1zsBYk49DzD7jBMSsu6owJXfVmqrsCgGNbt8dDpowFPGuwWihZ7Ac8+V44kZ5MI0vDGYz94x6g6Pww+2800VwBNbHZJfoX0z+iIftiwl8pgDK4MR0kzFJKIuwX+mmzQstj9NA906w/NOAYbj+6nuQH7L55kd4G3yt1FvaHdDnGbR1BM3dklA/rnlofkQg43zu7P/37vwSLAVoRxNCvfUISCvT981GHx3qAYXcgXL5tlCtdJYT40pSSimmI+bjsMqDqdtwdqVnz6uA86rCnK6sHnBzkX7sMihsZt8XDhgC9vGpz7nTLn+5pEZCs6bQuD7qXH98VA7oia2Go41iJ1bh1+oD1+h/oNifhJsgpnguFWY12WFcjndYsFG2jU2sFwA8rn7MnIgLonqc6MQE+rjzdnoUphaNhv2JnDwBlQRSK++d2RvQ/d4kcM4+DLSYsbqZAhyWbgI9zee+gLbTXqrntYXhqaaBSZKkFiNuCmBmTta/fhqcX6K95JE/xnN0+VBPTLL7xwFi7Prm4Gw0L9Xt5omDf7/mgSXEgZkY+qRz+zWzzzCEbcoHHPgMev5O5vh2fUKp+uQI4umlqKBhJxMPfUOB18KKnv97mRRFDxZj7thbH61HXDMC0zx5CuCf1UJHVTFmbOHeIj4NfVOnUt+PZ9Ja/hZxKxKa2qYQHbJ+ocLkGlEdOIa1BVcPzlHTiS5dV7F4rf4tkSBDl9KgUfwKIO25OJcH1jYks6XOp+JJQDn60Z6b6Cuy7suFn57zn0n+Nq4X0Xv50C7STi1++x13chSZtjIBDuHNDb+gBm+FEu/deFvlj6k+cI3CXdrHkMvjGvsPGGrft7Gt5DunqWpXqYXaa3twPu8LCLH+1BPf3trZ6DQbUmM6uw9lbKtGQv8ryGqfocvLZcM20H0677szvBR/4K5JhvJKLZKvNpCtx7j+PzM0gd8uTFV9jfe+7HOlTqo2Gk6UN+CRXKbYclJlpJ4fD5tHpdLBRp0Vh6DL33v97ohJGcGjl7vpOIC1QR3fvg2uEfNAdhgfHxjuUBjP91EyXFIPYVh9NSdDBqf8WkOAzfCHxqCFNM1b9YwNPr1NQ2UF6gvnoGvvDvX1iBjNJr+7cMkQhHuhYmCchPfSrUBk4ee/HmOvzSQD9JgunneuT2jyLe/RaXD0LmvMEEaXjmafjpAPiCJ8PoE2w99aykG9JMRI0PQrNWP64pWE9N1l36d5+ewvn8CRLx/VDdgzLobHu2pgrW6A1Fj0LBwGdzPJOoo2telKYwZuy67HkYW3TRwR4ymt6+HgNtXCroPsDi/EnlJth3hNf5KxzOHjLxn8K+cds7OBwKhQtUxsL6LRKSXbCDTeTk7mnsG4Nc3rxQkILtlTCM2Zrs1z+P+8WMy8eg1hPmX/OQ8lqr6Dr0nvngdmiBRLhYea15wiGqyEOBUGD1qUMktNHZLdYL5w9aXhqGnmczH03D7pR35+UW0beEoyZJMCtu8lEu1J5/8aXkn0lO29/DrY0LagIrWJ+CQk9xaDhJKpOF1blWEV7wY1dq63sYa13O0PBPtW+aHTC6Yo1J7TeJsF04r3USprjX+5nAi+Vl46HwYwdPSBM800v/ah2aVfbMU69i/1rNE98OfQKDL++BvMWlTjNrJML8w7PcFSgsmjxJsY74EmXcEtCXxV7vLJyWiguxhfueN9XegOVRnkcy4bBD9+18uBInX1QG77VM8M/D6PdezLv+oH6yuXT3QvbZN8FCsIwQ+OULtVU3pcKgUGL/jRhopvMxJwXSxMbu74SL3MsUXBskQu2h4FEBKGBj6SEOWTt9Lj+C2Zx/MzMg8yvPkVyo/Jz6QCksC184OwKfmxgUc/3Fe9XOPToBzZiO9p6CLyQOcFrAwMoclvYtLgT9/QTDb1C2NDTqJ2RV9OuYgXeevT8jSOlCvGq7cNsetis/eeUE+6gmV9ygV4OVejPM3dXv3wl/lVl9+gEvt6Y20VC5EOepbeI14XyUtoAnzKCaz3sJl06aK03Db+eZ3PipXYiw1wblYnDxRvzfw9BSere3+FYXYjOQ66MszFMQpCOg0wlZXS14UWTriBe8djKkpQw+2DawsxpS7lcyb4RNgkGCMfQuhGBEwNUUuMMsqPAZrOesr2+Ca5IR32fhJ9VqgVVoWLjuQMngQiTelS9ggFlZ7its0Fv6o/Je+JNzfMgERqi/vB8BmR+ofY2H95U7uZ9AnVuFc2/hZqyFXC1s4KD3bIMyzatxy9Biz7UHnIwuROGYTjc/1GaX3CcOM+SOjQRBttsXxKPg8g7/W49gkEsbbwfUUDg8w8jkQlx/knJ4N1S/wuzBC7eZ9EbEs7oQ/szuvWnwoCifYDaMsZkzaINkpQIxyp0uRLBAGIkBzly7XsUG91qJzMhDu8gD8mqQh1/I7yS8XVsbGQZXRyTSy2DZVdJsFeQ3/qDQCDeOX2/7Du8YN3CPwcwqcft5+Ovk9MPdbHjf+5hd6vDDFgkrXfjrSWO2KeR16v3yk8OFiC17JTALybaxN39Dt4KTupKcLoT9vutOzrD7ZMI7Mlzsa2D2hxHdFQo1MDSCM7gFmma7d3fBMQbFPX/hS/EzJvxcWJ8vU+liUHPQ79dhSGvMp34U1h38GHUCRtheGzoFw/e0vg+C56RZUt/DgcjNuXqYYbJIdMB6FS67Gm7E5dXjkhb4Kkp0Wzc8RRmm/Re63ztSws+DfP29uFUccrUWm8vCIwoa2xf2uxDTb+us1mHmC6OX1HwuhNAlUzNpGCP9wOYqbNtytuw2PHFEnOku9FBYPzIi4kL0fOGKnIVN346N/4ZZPbFrkgcxLin7Rjv4Ir9DwAl6JWp6uEHSWYodv6VcCEW71qtbDrkQh39k1NHDT+/5EuQhVULKO3to2ZvP4wx5Qj+5kWF5493uSUgI9ckuQfv5o9F/4e0VDi8taRfiRr6PpTfsTNaTyoeCB/beL4NOXItTVbDMu0m7Ef5ovBG3Twb5F+21LALPN8QYS8PP9IJN5tBxKkzTE/Ls/pJ+D/Ll76eKhBKZowl9CsgngcE/I1CXbfDcHLQwYR/dpYj5nWifOgNrn4gO34c+d2YYsuHXvgvXX8Ly0q7Wt/B60F+ZRFW8z94lMR2Ovl3ZkgvVLtZQ9kEJsUGHXWpYp51P2vZCR+fLR4Shv1qighl8N++jEgBtr/ln3IeCF8IY42FPJtm+wdCFcKk939UB2ey0TnyHdU2C26iNkA8eN2pFIGVI8BFpSNr94pkSfOsoqFwPqQaSc9phWQv33j7oPThswGiMvHpNwXYIdia89FOE/qs3ltQhxw/d7OtnUJ/q6ftc4NWDFA+94evWp7aZkDvj0cFv0CJBIuUnVGCp3TkLH3g0twhZuBB6XmHqUrCJ2rBMAbIycP+nDje+6ky6w31F7mL5kM4wPLUMLjln7K6GY7uqQhr/fZ5TPvj7ogshlshoSWntQiRvv/iFATLsuyCj+M9gEdUQeEko0+oV/O5j01sJN61FTOpgbf1C82f4gIv70xMHzEdhWD0H2g0UVL2Cn77yvv4GuVvmJBivuOBct5SzC4qbU4jx/pNGUPgQlBI59lQRqny1EtCAcUfNE29BQ9LNnemwZ1tbZA5M4ZfZUQJ3HnkTonUTdZ0Yvt0Ivguxi7SEgw2UST4w46nX82dwNihErBByrCXmvYFLOnGVd9wQxz+Jml6QpJTRFARzGYuNo+DPq7W9j+C+s4MXn0Lrvi0TebBoWtCpDO4MP/W7CgbJ6hs2QvYVv+4v/353u5XvMBn950piYjT8ukWTPxl+F17OyoTzAYMR/O6ox5gf7OLQS3b4sSy8ZDctTEA6kT/5WvAWeYe8EXxx7uB7S1j4WUvLFoZ2Xm+7AY8G1Ue6wqa8NQ5fqGInmRYKH+RdORgDMxd1FFp8XIheVYmaLth2gN1wEN7gVlM54utCpB6sUEyCdyS5ap/Cq/Wexvkw8PfojzKowdKw2ghn1tUDvsJWtw+sP+B0mFbKOPQ42DfB54d1pdtHdwF6ZEw/vAxffHnHdxNaTAU40wdh3wveTskG2ysTI3mg+p1trWowRW5t9jKsLy27ezPoX557MntAqVHjke/BLsTQ1Zk7Y5AqOGzrAox5px+mEoL4xH+cDoTsn6o9H8Ch0E/Mj+CNidbHGdDvvufWfvh5Z17cGKSW/CmyALv1UyJFQ5FHTZO5Z2EgnQ1hB3v7htoc4fe+xZzGB1jXE5JqX6GRrnNXP9zvVChOG+VCUJgUWmlCIdXBM6GQasergkI4FHR4rhN+md0eMABPzk9zTcLnl3S1WhNcCP05haFu+JzzP48huPouUlcyEX2yrM3kFrRs2zvnAc0DnYLv/fN7nUAkrAz9FGWchDr8JC5xDpqlxdfbwb0nvY+EQ/6BLNW38My63vdPMPHlb9c2uKtvetvXVJxHvFee9sPFGlqNcfgqNdOCIw3r1zrqrAWpmA6zGEG5yXt5lvBywvkzQ9BzjXZ1Cq7+KYpdhn2ptrIUT9CvPjPOykO9kw8FEuCPpSXPPvi1W2LvKHxy4UbFHGTFy7ueYx1fWXINwmFFnreTsKveTIs1C/sL6/qpo1DoysyvEzDh8misIWRxbL22DKk4JFgoXrgQW+2jiulg46B1kBpcbq7fdRU2NeqceAQVtnRN/oBmo9X3J/59f/Ol9C9o8ueCgX6OC/E3g3/JHLYvT8ZfhDvNDn5+AB9n8q71wznBfTI7cjH/IaNuDrjleJgnP2Q4WTxQXuhChORlBNXAwvJHUq1Q5kFB2zIcqZtlVS9yIZSMnwvfgaXThc5P4VaRnvjvsPD2bdUxGHh19+Q8JLrTjrq+wv4l9nHcB/KLTkeFwpzOj0pF0PM260g3lCNfixiCrmLNCtNw2/D5kfUSPIfBJpKm1IXg7L+hxAxv7l6POgrHX9HMhMKAAsPjFTBEt26hBq491EhuhX+uKmpoVmB9TCwW9eF/016pp2E314NtwfDCMRfH11Dt9Le9H/7dx6vZ1AQdzFnePX+P/Kn54FgE5YY99lfAoUKlzzWQ+9AW39Z/11YN0j1QWTVxeAhKtDs+nIaVbCc1V+Cs7dEViiqc/+gEn9FDtbOsp9mgkxU1/V5oMC4t+RVWv40d6IeqGluixmGru6P6Irxt83PpD5TaPJ9JW+1CMGn/MN8B6TRt6Tmh+OL8G37odnb/EXG4erV0XBZOcXf1xMLY3Z1Uq3Cz8OdLyg+IC8WaHSO0ahpWWKnB/4UrL2coPrkQxuUhafTwe9MOQUWY0XI46woU+Kx97jZsuGfDehfOH0pL21GL8wMPuxkntHoTxSAAqWTf9GlD4ovmNidIX71U7gZvXcpy8oPH9IQs+RpciOYjV1jFoFxXce1h2GJmlvIYjsu+KvoNffNJDpSNLsTZfpX9jFDSUH9bapsLkUR/qSoLjrh5uhfDWYf9Nr2QIVdQj/Iznvvw1jZGGH+4tmoXfMzzzlYT0mzqM5DgycDBj16wtc7NKxjGVLMrRsO02+VLSTDnHb1pF1QJ4nDmbsd558DexZOQNfC/XFP4NfruvXQ4OMDdNAZjWwMDF+AhlzW1P9DTwE1wtBPnoDtHh+egpil92hoMnFDbdbgLcVU8z2QJffgvN9hArhqXoBswcIZLpbTHhXivErTxHlLr/ClvgCMdW94swDGRfDq+XvSH+5Z1ojCkYHvQYbjqdbzWEDJE7wi0hE7W/cdt4chzoXtZ8Pfx6TsjsMmGUW4OyhNSK6uQqDqtrd+H+YrrMpyGZqaajRdhzdlLrUHwmYobezNUpjzU/xe+ehv6eNt3nDOPTFuxwsp9PzM3B1yI9T8JV+gG0ZfjTCV2wjhvTxWFwX/xX2O5Ak+cnP1yC97nm4j3hHdKJ84GQort8/sfQCn+jZ+JsOeX7XIVtL6qsHUCHjvq1rAIl9oq72/AaOs3hTpD2O9fypBMoP+nIsXz0POXYGc8FOQrvNkBW5fIR77DN0E6G6OwTkMi4+sozhPGJld/QO4D3tITcCSucA/XGOLQqX5YFW5RyfqjA7fb7fpgAs0brnznnXQhCvS9M0Xg89hHjtLwiXGZ0HVYmWezOwUmC9T0P4NmZ8WeF0JKT4PLktP4P3Q+SVoBhtLMbahBmbqh+Vv/XH3J/Qhu11MdzYC5dh0FebBmgSSdtoY6TyqgyYZLrPOdL6HCMf/FEXiltJ2ZfR3jHDEc3A+TvncWi0LfGfrYgxv/zoHVDjJQfNZLRQV6p6qznvj3Oe/2kVNQxaGvzALmeRWG2UAZ6zCrGzCw+xjpMcyfHz/1E9Yf2iE4C+UIpbXf8B5FfTiJ0pU4UZZm4w3JhLdSCPy0IXmjHMatqghTULkS6W3pZdaQamJb5DV4rM3ZngR5y0/9aqF1JQ7RvmnqhuX7DmYOQcq+7BG2ra7E/aXriZrQinbvbQP4Y/Sz3hnonKX/acs2V+Kw4rVUBrjxKIK8C7a0lJnwQlch0Ztn4HyNIM9D2BuXuJIMtyvt/vwMRpqyaR1kciUUZ5UFZaCBxTUqFSikZ+NiA790rPtnwY4Ak5KfkNw+HT0LhxdDnFfhlf0748ksrgTxrM7FH/pQB5jfh61GISXvIKlSZM8CjD0huLIOLTOFO2lYXYn6XskSZniLNlRODnLN65aeg5rPg+PsoZZck4szHO6wlg+AAcMlHBGQtZ5lLR6ytRy0bIAnC2+m0O7E/e2dlEcg81z00DHIMmT2QQf26sz6n4c576ttL8MmpuTjN2Eqh3x2OmwRSWb5CsnZpQv9/+6j6W4fh/v9TOladrsSYe8PTXXBH1/ZWgbhq7Gvymx7XIlz4aER+nCluvjmaVjUNmhqDRVuLA1WcroSFcyCtXXwb5BlTjus/+Woug5Hi6c7+bhciYxO8woxeKqjLk0WcgWZ7rWHuakTVM5QP9pvnAwzhwS9nkA5f+k9DXAPP+VGB5RM/Dr4HTZVa4kJcCMvtuuy/gfNpU1/y8Gc0t47l6E7m/ZyApx7FPUtHVJQDFXlwoVdXhxO+/HesQxKMuSNbZv0g+dbDa3fwVu/sjqWoNIm99tNuHc0OpOOD/mm+2XzI9x5t2q8Bf4X/rK9G/awDenv4nclVK0/TJyEskVUX0zhzx8nKi9AusMCYe2CroTnY1fXPmg82WEzChta3fcwC7kS1TRFFRrQgkErSx8GzA3HnIZKZXn8nQddiYfWF1kHoNgs55ZJmHCpIVBSFOM+dZzLDm6RNKR3grZzF1fdoFUEVR+/GNZRwrNRHL7N+/tGDvL5K7qdh326qcKRkDnNkj0Rnuri2ZYBD9lplt4WxzVz0LO7cCK+LS4IXkv670wBpOBU4+6GhYnvGIcgI4X6xhTcUO778/OQK3HRyXxuFjYFdQ+twqIRi/jD0q5Es6WIpR3sOzSv7wT/m3mrRoa0HfTe7bKo37fdd/ogcT/36ii07FJSZ5ZzJdJMtcZloKymUb8KbOe2/nIC3vOIzGlXQD4+f5fRB9PeLiWNwkTj/Bv8iq5EEsn2thU8IPPZLAiavbtiEAUTDjNoJcGf5Fxm3qOon9329CLQMVGIRhrOLytPXoLv+Xk/x0DNd7xNj/9dHxeszYKDH0iJvqquhLaDTFwY3PZnOToWFnsqBVZC0aqeb+Ow/Mnn7kWYbLy3VkLNlbhpc0jvHvz26dqxMriXbVClGmrqWio1wbSCo8XsJ1yJx2wni/lgpO25YjEov2Xny3OQTezrqwQ4WChRkv5P4fsluVCRTXnIT9uVWHUpGw6HTU2KI3Hwko/X1DsoQqctIaSDOj12ifku3MfoTxTCsMQi1XKYzDWmXgMdjCfNfxoiXswXzs/CsYoem1VYcCs+QNQI98db3HeEaqyNBWkwfqqgNBvqvUmqfAUrO1IPjpmhDwmzyCzAw84Byn8gu0KstYC5K1G75XWUKQydcki6AEea9mc6wD3PmLoewUKbEroW+OpH3s5uGGSYyzMEWy13S3SfwXNZNRSGoH+lq8Y0DLlUbLAC+572ePBaoJ+v/ymzgF0vyw++grdfX5d9B4kSQdV6eNZtJ3fPOVfi+PEnIsOwm0lebgZSjTdc233eleB8u5muAs+fbCg8Ackdj94Znv+Xn10MIxfR7261cs1BzR3NomuwKrNNkdralfiq0KuzHQbWTViwQyE5xx/n4JQ8R0UUVC/QYK6BDWwjw3SXXIkBxZClnXDHeVnavdBbbfX5lIMrMdv96u0yfHnDrZ3iiiuR8u6DoAgk54Sn2UBO0xm+NOi8ey20Aya/3f2b9qorUarlzsQCcztG+bggn4+uB+9NVyJv31SMCLxVFZEvDcW5+aRsocs9q/R0GOMYb98Pr+pn+YzDr1LvHy3C7MPCDzjIrsTzroB8fvjEZ7JZHK4rK9tdgMLbPJUzodkzj+Uh+LjHeNcM1GQ7JPMbGtVpewb5YP5f96RGwW2zE9VJMP5OoFg5FDfcc4rKF/kSGr1HG7Y7bS9yht23bb+6w1a/D6sBsDrW3KsoGM97SvWsAqpVF7d8gj0pZ95Sh6D+DPxqdaDbkeA5E2gkEcN+ATZ73F9tfIC+d49ZsBO+SHtoOAAvf5qgpo9C/vHMKJ+CLC0lbLFwYWi0qB9+6WcYGIe3Zg5v/wXbc+5bTCSgnqtHQ3/B2BmNt38heafLS6lEV4IjLHKLDaSKLxJNg4omLpT98JH3RZlx6PfB0HYRTitRW5x+hD7qIhdmDZ81OFZegzFrDwJj4AF+bcNKGK722q8OjrtJlrTDwG0mfHdT0D/9LpsGQV4Ov+Ao+PqsqEU5nDhrL/YTujWVXZiF7iYsD1chv79UcV6aKxHVJj5RBmvlJPd9gNtfx/63An1+HWHme4LfnXXREIPXf1SQZaFpttaOjKeI48m0E3nw99Yt3mUwpqisfRl62V0dkMvE/hTKyakK+ZqaDU/CF5tiaplZrsTuhjGPArijOKv0DXwa+4pjFW7tOPBa8gW+7+sfsIan+ph5rkPSuoa5C9Sl/rJLPwf7yKuDhqdhakBAuDXM3DjkFQp99592fglvbJvKrYQXt/tP1kFnEfrUylzko7LS9zpo5XiLqwN2ujzYsQH7DXnUJfOwz1Y98FaAPqe2V6rDGoVTV0+VuhL2PUp5FnBf8n8LNvDIbum/4VDG9yN9KQwOndGtgsKveSIb4dk5mQNb3mD/Eyu/zAC3hGnl7oKs98rfqcCIfXHtdrD8syW7M3TNEjrrDi96RzhmwE+hRv7N0L7EpL4L1m09xzwE08iOO+LqXQmddd1zabAmUyo7GzJZ0XlNwN9XE2n3NmBeMnXGwrBeZCPtEOzQkZtXgusJpKPHocaet2GnoOVB8i5/mM4ZtiUd/hFnMMiFz67fTy6FMnZVh4e+Yj2a/gZPw3ybYz9WYFp10OH9nVhve+cQbehdP/XDGBqfvyZ7HjZ3h0Wn96AeNumnciHT6XC1MijS3J06CLmL8igYe7EvjziY74bP9cTy98H2O4sESx/6GdPPeC7I0fNt4QCUP7Bmqg/bJIPfuED9gTI2X5j7afZaGOSL7VHfhIE0Fsl035FXWQMrO2HPaYVzylD1NiunA/y8pe3mLVj84WGTJ+wocM/UX8A+GP0f0xmYVTLifAm+/PT6Sxp88/zp3XbY1fj8Zx/klCzSGYOB7VUFC/BASdeeDbjS88tj6yLq++ieYRZouLJvSAMeqdg9RoIMPz30fKCx7mRxKJyr3iadtIK83ZxOzIRfPbqpC+HT0QG3OTh9YGNK8jfO4zQKporQX9ijUgOms9T5bq5hXbhfzdCt43uH56fZYIneSxoVGBIlVmgHvx0353GGd4jgQHdozz34OB8ORuhMDcIR1yqzaXgj82j1CmS9Yvx9/g/yR/+69h847Br+inbDlfg+VszHAnvFebP14U4NO+oI6CbX75gAD98425cOz3/+ln2O0o2oIeS5L8P25cSQm/B66WhpJuRhPED7DUZ0Nt4egYMTbj/n4KWtzumcVG6Eg89RtgPQUWOnnwQkG0wvykN9pQajNLixzYD8Gwo4pk5SUrsRxbyrFkywcI9Z4x4Y3nI3RJPBjchmlaM4BV+n/rplASvdS8dtoHd9NVceTE68tGsSSj72Cl6CtPNpm5uQP7zhFj2jG3Ft+f00MxN+fzrcmhN20Vl1C8D2+ol8PagmZtaZDc8lvRMcgDnUDEmTUKrMYucyDHvv7RzM6kb8okucjIZtqa8vpcC6YyVV7VC35PT+bTvdiKjXbxNYYQjTQTYeqJSfGCYEE8xTb56CHYIZr/NgjsKHhzPwIe3iCh+bG1HuQuksDnkV2afkYFyPntGzPW6EZ5BHSyE0DS7UqYC+7z8qjUKTe/YTzOxuRLDDV1tOOJiiPSQAd27R/CYPl8SazNUh84szX/Sg1XnJ92Fwz8vppEbYbdXE2Qk5rIpiB+D0xE82di43YneVUBQf7J26wSIOj155e18OnqnP2HoVnpBtNsyGGXSvGzph84dr2oNwtl2obgrGdFEVjnFjvPstpRZh5NvX+RtQL59XchuPG2GnTSl+HD6uW1n1gyVb81zvw4cJV1fj4TEfSdd0WPl27XcuVBg56TIEmX9Flezbi3mJZsmJwvnSmpLD8IqOfoUGnxsx5PLzqAF03PCuOgPrVQo/x8PFKfOeYSjDFnfjP3434qI+E60L5HPrjcmG3WpanCXQyKYi6T2M+y63vxEuSFlJLMO73sF3+ATciHcsKmticHN1xUMOVtj0U8UIIa84nwU9hjXCJOYX8GfP10MTcHS6Ya+QsBuRGzKdLgVtfXeJKkGHgKIKC8g58kvNFn5JUap3hJEMiUMJMMrEf+MDjFag9WuBHa5h9D3wYxFVfdFBxOto3qm3sFvQqrsWRhrZ/16AV+/WpgiJuhG3V8qEDsGh+oI8JVixmid3HL47PmbmBFO8F7qfwE9qkhdz4QOrWxOl8FDJn+lfYrhvhYa0CR9G76KgF3cjnjJV56jAha/pjF6wqJYiJhj+3W3N+xC23UnfZnnIjbiVMBttC/9yH9vvBGfkj/RnwCC9063U0nhfXbzsabjs/WElDI5fq/WLg+Zln1mewF/PzcQsFdwIRUmXCluox5Gi5wQNnN4LPIVxGfZ756DgXWobTkXEbS12WQBmd0sFSsBGU2GWc2puRGzP60x7GPnRSOUmnLfPl3gG19LF+PqgEQVj2SjkqJ7XX4C7nb9EKeqgXpdEJDQh7bBfvQEMUx6xsYD8lHpbbGGrVPkjRxjTKHmEDEMf+uq9hplXc98wn3Qj7A18zThhXMq5RQHIvhR09LOhG9Gnfaf/G7Rkvnx3FNLfvrXJYoQ8ydd+dwrmZ940K4cVDy9tYzF2I2RnWJ5zQdpXH7UEIWl0q8klUzdi/2ueletQY0M+3hWuXZ/cnw6VH9kbDsCjGh9/TcLFc8Kxy7D3w0Tm9zNYR6bCk+Nwqfbu/CKkiOlulrZwI77JZSx4wW18/hdqoYDDbXMGSzy3ZGVjF9zu6vVkH8w1VaH+dRH1fHsu5y9Mpn9uRmeNfkLZ+FcahqycNLgMh3f/znsEV1JZzmTCjSdS1IXwl1Fj4okrbkTBy1BtI8j/wGj1LPzR7MeaDI+rrDl+gV3ftu/7Aa2XRVomoOepUPl0ZzfirU7VVC7U//A3pQymBITvm4VnM06YSNxEnoiqd16Cl+lng2/Acdfe0wmwlDlb5COstI7sa4FPZT0ie6BznJDHihvWzfzKYUqyG6GZ+HKaER4OC76nCuN/STlcg9cNKvhc4Mh/+r0+UJmhVPxuAPrXxJ+pIPj01InsaNh/tOR5Jdx+7EXmBFxxkrJbggdF3wpS3ENesNcNywW6EQPtHBmq8Di7k40unL91T8gXLiTll5bB2Y/6rh8gF2lJvgWGhLX7RDzA+3WvayVC7UfMO55CS06r0hGopvgj71QU5tnpG3UPbpx/eeYBrLozvT8J7swVfzgG0+UTLBfhmBGTwF9oKpNHJxPtRriOGb13gjnFu4LcYSfzd4N7UKFDsiIuAf2ApiDwCTxYK2ecC0VNJjhmYdfYJoNwohtx0/9L5yFoVFzwRBnyDzYHP05Dvv2UtHgBNzzjRV/BLpvY7Sswe2CUku8J+vhMXLsYzIowSJeDTzTOf0/KQv7fTCl6BqsVRwKL4DmRF0XjkPmz8BrvCzfi/pHSloNQQV4v4zA0m7Z95FeKfevlPrf78BTvgFkCfMrVIvAHOgwZ/7AscyMOEFFv7SCnStcjZ5hbZ3ZksQL9M/0ix1/ox39rbdtb7Aeez/hMYNjds99zoLh8d2UpfB5jkVoN1xzYz1pU4/2MN47ZwudGjQecoM2Te16FUJrqx7YZuFkeNf0bHufR+0z1AfUYvr2ssBZ5kPbicQUsPacfWAuLnxQs09VhvmeqfAwgR3a5gwWMeVphaAsNAxSMyhrdiBfLWsofYB/LBaEWeE90vWUN2hUp0Sg2oS6EHs1qQANNyh4DqP1ifN5oCH3tXcP4OUgRUjxw+d+1yquCF/CZedKudXiFa5iJdhj1HC1Fy/JP3w5r20ns780ZF5wge7vHWXdI1cGpVwRJUrJTi/Dp/Lnxv5C4Gj5CN4U4vVR1LFxA/FtDnSog8bzPuRaaki65/IL9W2fvii66ERM6vt6y8K/uXt9j8D45OMQFqi/ohvlCQSH2++Fw0t4v5jWsiWh4PA8zZLrT/sCZmOn0rb/ciClV1ru6627EvlNp/ubw2n75UGvI9rvz6X2o1sxSVwOrZaZa2mDi2aav3yAptuS7ECWZoFQjjx+C7MUav5ShvGQRrwMM2fHINBWKK2RZZcMYkcqrJbDuew+pCrac3vBpgrPmzG+oqcjEadXOMUlY7qL8SxGK3c7a1IQyFUIKNgxkYuVOjLYj/LnGYEGGdXMHkjKhWErXj3aYejRk/jt0z1KnnIABu8QqVvaTiZIaUi8lH5lw1K1fZYIbleY3FWBBY8a0LeT9epjRGWq/bDzoAQP21hoyCZOJIw5tt9ihT/hADD+kirHlNYDlq5Sv3KBxuUGX/79rs4y1iH8+686kECUT8bnFDQwwODxmdjc8Few7eQlWHdCIzocPW8JK38BOo75vNfDpTBA1kzSZaKQ6I84OOVYkTfnhsZ/1OrYwltesqBRqK4Z/q4auhxtpWmDf/FnBegUykbM8Y/QFBvYFeP+AF1J+2rArkolrQcUdTvDX1N+GdLiWzLGWB72kFYXfQM0L2syLcNdcEZuiEplQERBW04QSik+cTsGbBjsYLdQwXqYxFVvIWVDj5ARJRwOUk+FFHpOvK9BJ4zq9ojrGRduqrAlNco84nYJfFOODO7XJRPfe7VWDkG4qaHUa2mVaMgvqkAnPk4aC5+AuUc5zlyHPr7GHt2BxClXeWyMysffP0mQdlD8+K/wF/nhz+AyTMda/TEtfAe47HRiqAXVGm+oM4Iiy69DoGTLB/earwCLMOKho+xd6XmC9KmqB9TKqdjaHjSdsi61hm+SO5etQUCONa+Ii4ug6b7UEE9KPP6OwJhOFcz/fi8PRMblvZ6D120Y+W+gZbH/ZCTo3dlqv25EJDbUTObT2ZIK1qHKZBQZV7s03gTevqO4Phy8Cma7EQ6GU/uJ0ONn8+qzgTTIxxMuaKwX9bjj+VYIOh+QHvKCTn1rJCKRJHvopeotMfPvSKysHBxh776nCse4O6m8uZILhSJH5KHwfG5e9AJlW/Sj+Qh/rtN/HXMnER9mLlG5wIjvN1B8uCExkRcAh00nVbjcyMcdCEzcMH7QcmJ6FEy4eU9JkMrE6s6hCgqqtN6J9oFPxwngYDEt0PxoPE/yZHqbDFOeMiTy47Rht7BikK2pT5nMnE4eqXkWJw7iOtPEj0MIsm6TqSSY8uAabdeHC0F7B03CYubQnEnb+EWFphL/WXtt3wtwNw3eDcGiS5U+/D/rGvLDpJNzY0MxfhjqpmjclfMkEl0tIpBvM/box6Q8JJZJmJBzUGsnrCiYT++3Htg9Dgcj5a7PwhkP5M+kQrD/+bXnAr2zs5EC4NhDcEwXbs2O7xh9gHKOPlJbgutTzxxRRZOKqn8FDeagg4N7mD7/w9R2OhOmSGgmPYJZu8d9M6G4pyk8VTSbuCGtcOweLdMQ+X4YRnpxyt+Hu98yPvCBVpXDARAL6TOve2SVIu8RlviWRTOyoI9kowLmNTPO7kGbb2vtgePGAkWgMZDQtik6FdAmcf7Oh1XygXSm8dctIe9sj5KnsCLc1nK35GHAdvnTInnOFH+v2yIk+Qd2xi2XIQsLz+E5VGNCloECG0U4VKg3Qq87o4M50MtFrGHPdGIZQW/edh/TNsievwMCJtcQbL8jE+QBJZjLMUb7mEwB/Xt9aXQnvW92aZM5GfdxL/U8LUkqdSzOGV5b3774AWY9XG/5Xgfja/G2Vh9eeE/oacPjoJY1gSEVj6/8Jmm75S9UOw/iSfL5Dan7Jx2zVmF/lTr590M7v7xNR+ObCrnxHKNPmtFwA+xPKXCogOXTbei3Uvvvf5b0NGNcxtjkRGCexhXQYHrJj4rwBcx+uknJh8wOlzTK4pTwg4CPMTHK2Hf5MJh7rHVqYhbYSqx7r8O/RT3Rb29GfreQ/EtCWqXsgBGad3bgWC5m/C6+lQXpnnuUTXWTi2V8Zf2PYXWHEdgEqOJ3+EQ9dUkVk++HZ98kfJyAfG5fJMlycaHqa1EcmrtvLyT+HR7meNRRDq5whhTWY55POLvOdTGiVXHlxFPrvV1DRgUJdB9rFh5C/6bSX5WHx85m/6rBh9qvpTchTxkCXDmdKZVLy4KH5S4ff/NNwa17nBJmQvpejNQQv/D4zPAOvRVD5y0ySiXxB1SYSFHR/Jf8U/pz93lEAFR9vd6yAZ6UXhiWnyUTyux3eSlAtRJbnBDzJvTv8DvzK/zUxH0oEaGRN/LuvjmNh9wz2HaG6cD7YVHVX9D94ZSGktWfhXz3JOI5Ambwh5gU4O13xn9gimdhkGW9zhdydy07+cOQbA2sk9JExCf26hv2RY11yEIqqPfsyDZX2kJiE1zH+opLPN2Gn8umKZOhZ6HYxC9JffbL1FfxQva2wl9KduC+aZzEKKb9Z0izCyYj/TMWp3AmKF6/X78CXur56BXC6I/t3OVTM6EurhW8bS2h76N0JsxNnXv6ElTuoL83DUnJVkyiDO+E8pnLEFuptHhl1gsesFWI8oBGbmkYQVPqWu6UUPuHZ3EnB6E6E7zOvZoA/HEud90CeiuBDzjvdiUTVkBEPeIEjKiEIajEL836ACkZPL25jw3jWafawwc+/rjbwQvVMmRVfdnfC749V7n1YmBFjkwhFHxSq1kO7zYZ9q5AqSbWLmsOdqA9/d38HPOh7XfcNnzuxXZ2C4ROUOxdf+xm+46bxYOJ3J4xVTd4rQoceubvH4dbG/cpG8EXOsvgzKXdiM2/gVxG03dnxphLusz2gfeyQO9E+tUf+MUydSKLIhpTaorUlcDTywFl5aXeCIYDhgAZk+fZ7ygAaHaf/EgIt7ayHP8LXi6nZbVBtcPRWHwwJFBQSkMH8CzSLr0CV5Cl3Evw4Ha/hC5V308xsUXQnAjcbXjPBBr2Eexzw1z2eNycgqZV7lgTdX4mX+8K+k2/mCuH639XrR5TcCcm1xxedYPxxXUkPWLZO8TcQTvqUrgwew/xbmmtnoLv/VPwa5M9guUKr6k4MMIUa6kI6VfHUBzDuXaFzMtz9/Kh6FtyWn1n64xQ0qo2aghT2c9d/Q9W7wiXShnhu+38UN+Dzlme9blBM5WBJAJx7d3HoppE78TDaq/IupO3NSAyBx5z8Gd9AGcG85VE4dWdP+yLMU7iXtwk7BQxOvL/oTtTuY/qvCcbEtu3shi236Uj7rN0JwXljawd4OtNN6w5835Up4QObeYwf1kGD3JfkL/DI670XB6BhOdOfHZeQD7daYwho3uXucRLGlEheModnq6dnShwQN5kX3dVwUMDxQwskopXyemGJz46EUWgwN+m3CLf3Nd/YhOsnys4wXHEnOJezNfbAmxeeSvJDRu1MLgk4VZhHqwjZlc8814SS9qOUT+EDr49Paa5iHIy3+Xhg35Wd20WgmE7ZqgzUy7L9ScD+J1/sBW+6E0fdBswPQd6OXydUYGABs7w2/Lx36fVzePjVegLdLXfiklFMyC4YeuuI+35YzDF4VRzyFCntanZzJ7pZOOl7IN/vv39/whqPtXJxsjvhPzXEYwizeNl2noPMF4/UFkCpE/v9qd0Rh5tVbjugt+AVR+5/13wvPnf6YN6bcY1D8L1deM0snDGeTpPzdSdy9zhuLYZ3Oc6UU/m5E63R8Y5HYcj3y1d0YFvxMVszeOGbX8nPYOT3zoBX8zCuN/zlBtSxvJivEYI+0D/SWwEP5iT1TMO/Oho9q/AG+Vc3TSjq9pDM9MQDd+IRs/r8MgzxsliijHInxmxV6Y/C/rO1wlGwYFSVaIHP6wfVe+F11WCtUWit4lWWleZO7Hnq9ekVJGcFfqmCtr2/mBbhb8MbJhJP3IlYUrW1IhSV53U+DpP3Rr2ke4b4Ta/U7IJulpe69sON/l8S52Bz0uXGRMg7LvI9Ex7vmJ8tghLUq+HMLzDPMRzcodD1hJdCcEvd4YOOUO6B8okX0Dtz2qIERgS2vl2ESWZBfJLZiOe5MFklyLc1XvsETK3v5z2Xg/imp8k4wPP7r2ndgaVsHQWFMIrrIO0Q1J0nuGZh7uXzkutQZXKJtrgQ42Jh530HA78dk2uEFH7++duKkJcqRaG34RveXdsKYW5X5763UESMPWkN+vA4x8sWuxNsK4GFqjDnTmaDHpxs55igeYPfsd3dygplNicF9kJFB86vtlD9sZBHIYw6+DvhLRw611paD4OErrLurnYnFt3HZfigkdd1s//gll5xIRJMWmy1KoD2+wr9KiB5PSGzDvb7hdR/gRRuCaa0H9wJm52N/ppQ7Rrdc0P48rZe4zl4LWB6PKIddRTXvTsJtl9oUnsOz3/Tv/sX+pZfGJLrcCdOtZTuUIfK8ewqBlCP0+uKJTxN+Ww+vRd51F/MXwD3udSZVMCMy+kGa/BcxIuTct8wD5ldd9Ugd3RAgT40KHrzo3II71Oe2tMIP94T0O+CbgeNxOiGEf90JXoFaJb1+pgmZHckXA1hvrBL5LUx9JE7jxtcoaV/K00AZJE8LFINL55y16UYdye6SrYEMsL7P8Kr2KHZodWg8Qnk3daXH5egZIrLFspJ9M3HHXOH4FaRNz+sYXPKB25HuK/ni7k7zBURL1qGTxqjZimnsP9LU4oxQ8785DMn4d7BPXl34ee59skQ+Kw6VjgOnlnOoNuy6E5k8/lqM8Hk3fYhHPCHxGUWa5jLzbycBAWun5LLghH3El1ewVX76bIqKOkmW2PxG+eER2R6exgUVKt3C1Ic44nygkdfyo9XwHcDZ5hXYYsejTHNKvpaQEkcCxRZXFOuovQgxjj7ApthNeun9h64K2XrgCSVB8FgLe8VCPPvxzVEw2+hm7tT4Z53Gilf6T2ILz+1Zgch3Q+To7PQSUx1nzyDB/E0xTD5Ptyh2DiTCK9WpHp3QzPb1G87GT2IcGEn8X1wrPKEpxjcOcx7pI3Vg5A4JB/WB1lPnxkch7sZawakd3oQfiV+XN6wY5DBKQyeGE2oiYd5k1TJA5weRDOD8u9pyEjnabgGqeeP7D7C5UGoPRBuvAe/97CsV0KJkC6TRriHIzO/C7L7GlxQ4vfA/4HeyhNwNOg6rwkMCazeeAC3vtT9Wg13kyVkWyErP0fMN3gjTTf3rrIHoescuzcUMh4aD4+DiTPRrH/gsu/5FiMVD0JDQ5K4AEeWtxVchbd/J9m/U/UgxKKOfWuESfum9bthmCvvi7/wpc8ap6maB5Gqr0WVA58s+JLKYH9gzeRHqO9+up3zhAehvsVeWwh+I3u+l4Zcm0LJNvCuRFlKDpSJtZBbh6k2q7lbtTwIkYMpgmywuiL94XtdD2KJ0N/RDHvLt4T0wJ9vlubY9TCuq3T6OjDxMUO9GaRv3qVxCTZx9wcOkT0IvXnG/XOwsFO17A+040oeMnZH/BVne8rgH7WnN2ug9zkbxnZIeSbu+7KvBxHPsEim8vMgPNtNOHbAyIpJO3t4KMuLVARlcox3vYOTNZJFjTB9vTNEOtCDUAmfECWgmzxN40lIS009HQLPDU5vb4D6yVZ5nVD6Zp/+MLwS6+5sH4LnPkliuw0t62peeUMnh/KjxXB0p87FcfhJuIJ6Geqby2VShnoQgWllWszwzlb1KS7If+9ruDAMjRUrt4M84TTf8mGtwapnBQz6b2l/PUz9rlhrFYY64U29ch3OuG1nJkNFhSTRH1CrrvS2RrgHYfQnj8MQGurkVZyD/ZHB8SUPPIiPNJbEB8gcd3i0FW67JcgrG4W8SdlIuwvDM2dH38KcI1ZtHNEeBAX9bldB6LH2eZ80FKGPqz0KVb037Jyh19CGZQZkZWKkKYQcpnw5b+GVz75JXHEexOPO+uPCUPIvx4IMdC8WSgyD8d9VmjohU+8maRhqrNbyzUPeMOm1s4kexAXbqKcOsO7iuiEJqgmU0LfCUP1cJp5HHsS6QuBrEfhby8FOFl7MOPDUNsmD0JZtN7oJXSYDt3jB6O5LVV3w8XXmOalkD2L/8aPJKtBMnXRSB56wLVkzg24td7a/T0P+6URXNsHW6TLHHuibk6El/cSDsD2f+vYedM1klfsEg9KvR+9J9yCcT9prCsBT3A6/JaEEjUgs8zMPwvFung437OBXoRCBVgsdxYdhOkE37w2faoa4Nj/7l8eh//VCb4uHQ6PwU8bTuF/wpJJDgekLD4KvmcHeGo6EvNzrCBsSLOzKoXK1WsUqvPZA/xZtNvpamLXoTpjcHxHgkIM4vw1SIUGn+uBlX5hQo3S8FXqKT5FFcz2IqKLzMkegsF3vlDr8ujeBtqEQv0+lreqEN43JHsNwnTQ0KFnkQaS4n3nsCAvF+nXyoUgf3ThfMd77/m2bFew0kgq/Dot3Z2uT4TKHQeqOUryHc/8FHnhAb23vQShfVBF3Byp06MS1QvaOWLM+aLx1avcE5P5Bb9/zBs/T1xEZhcm/oiYW4buEbXOC5Ygnja+ABVQL2jViB2lV8zNvQbl8NUa7Cg9CKt6n+SZkKa2L8IL9jBxGYbCYlDrQDXtNa90F3noQR674HJWCwy/VKVXgHv0X1Z+qPAjTaKugDnibdZ/+AOQoUlsQr/Yg1r6kBj2Bm85CTd9gb+qDqHEoSU97ZhkWKLvt56pFPQ4/nhCCm59aimRgYdnhtFtQilObpwaaNPWOfIbPym/n98O41Zs5Lk24X4XRzR9KVGdrPoC9tDqan6HWtllN1mYPYpqY2MkLc0unf4jCpbU9pf2fUZ9nRQOnYBvFcfNV6Mmse1m+HfWV+Jz/Bsz/vOcXGfbqhH8IhLsiKJ99gQ+7Cl0G4UXrK1qzcOCP91mJDuxjXj31rjBOeDkxAH7ZyXktCvalbj0v2Ys8FiTJKEPN+Rk6bei8repwMDTgLblYD5UXgo50wgEGm+3DsECbW1F9CPnl8n7XKdg1f33uLGSsJllEQjXzJ2sfoOatxC9t8FpvYv532KZouf0WlSdRGlS/4QUvyBybDoMWcfwOS5Dt56FuVWpPwptSqE4f8nvwl1nCCx/a7ZQZPAkRUR1Lbci4WG9gBnPSH/Z3wetyF/wJRnxurG1+GkZxuOnawjaiUPUmbK1bkPOCB+bEcxx3ehK58r+eesDRsarHwbC9w/jOT3gvlotKlc2TMD1qv6EHNXUrViwgr74m3x0uT8KmTGm/L2wLU9wXAWPW93JOwujiDTMFbk9C8oyz2XFo5TBragylIvQtQ/g9CUU97wtxcNHtzaUMuCWpznMRBvON9x8V8CSS5yKGT8KP4sfGT8NvGxSVrqKexF1/s9oAeMzrVVsUHGpPpR+EW6yF90mKeRJjR5ZElKGRT720Ngw8FGBcIu5J2CUbnP8AMz35Hdrg75DqhzT/eRIPpoWq5KHbiGaT5n//4nW9ywjm8bxeCZD2JNTYtGijoYvPD7ZUuJltfG4QJrXOPOOX8SSeXxoqkYR5jj9qlOF5RgZysKInUVzZGB4LhWZj0tJhewDbQhf8ks+ixqTkSbxRETbjhPRax68IwYFs109eRp6Ec2T9RBhM3uTfngh72PsTW+CqvOtBamP8/i6vHguM0m922gtTPh7p+GyBfJFd+NMPrQ4XH5iG9ff+zv9n6UnIq5+JsYbF7U6VjrBuPnLMA171GpTvtsb91B12I/AAV/PDRfifsJT74Uv4/Ib6YQfYpxZtTYLkF1ORflBZTjm5z86TqG1qaJ6AdqsXN1dgcUTngry9J1FZG5/tDx8uxvY9gD+Kkrc/hi8YHm/4XPEk9qpFSEbAEpYg6yS4asAaMwWT/yY9On0V6/liT6st/DAXT3ULHrnySkvkpichfizFWxYmFEaUqcF02ro2f3hI9lTjH/j8QSvvyVvIj4Y75qfhtccHIm2h7OtuCU2yJ3FYl+GaESS8NLIuwLthfikP/10PeXptwIZDpL967p6E8UkTJUvoRavkdhmytDw+l+jrSaj7EqnP/ldhfYdj1cZxALeyGyIjI+PNSLaQjDsKSdlRklBGSkXJ9jy2QlZGSKjIyCiRjNJQWWnYGZUUkpER4f321+e6z3Xu57nPb50Dd/V9/1IBX16Ku7AmFM+X5/JMH1rVeDNawpmL8fscoPdbw0MpUPd5bNot6Gjb21cGK1RPjH6D05Y2GlJhgWTi5EqQCozjL3imC3sthw1uXQkkUdINcWX/LMjrqoOOG28T2mjEodPiqBW0NMi5dQIqOC6Mn4eHBNaRleuBpGPtWDxbeiA5Wvb2Cy8Uuc0m6gXF3FPMy2Gu0MTtephIPbDQDJeSKwx7YIjksjlPbiBRXZIo/A9eDbWhU4TjzRQ7Z3joyEOuAijDz900Du/ZNIsuQiPzK75MtwKJ6ZunYg6FgcSHakU5C1dmZvv8IcP2+KJ6WPPKRXgW+sceC6ArCiRj62171kOvIO6e4fvoR1ZNjRlYeuj0DZoHgUSHmSqhAq/92lfmBqNWGjl94GrLQa9wmNfPq1BZGUj6I+quPYc+M6cX26Gth/U0V1Ugcdm6Z8wKav40MzkJ3106VeEBl7bJ55g/DiRTgYos9vBIiuY5dyh1bcGzDGb13/T+Dcdd2QdpawIJczVFfz20S3/lyF8bSA7wzDZJwjLrbcoq0H+T1Uc3mOdqbVADBaQmSl9Dx3vRfJ3/ru/P2+bUgP16hsmeMIlljpYKv6d9EHgOO/3zpBieBZLDA/evccBy1te0W2DQAUdS0ojnWAgoqYEf3LOF3sBbRR2Ga18hnqoNc8dhlrqxkzs8xTL80Q/m8N7ZJtmCOHBYZO6A1V2sG3QhH4tWrzdcsVPOuwedTqtvroE1+vtiXkPKeT7po+8Cyc2vctmu8KiUMc8lqPLmrFM1bFrNfbj8b23wnwzb+0CS6lCcywv3Srz68agT9fvIwbERXhZm/PQBdrGNP2Ptwjx7w1BE4Lei+a0H4aETM1k2UDL8Q+STkUAysGmKvRV6hHDH90LWYYYcju+Iv1DRfX1YcEREzRImXciqcYDM2vMF7WOBRPpLncIADHa+WjUO94pI2MiPB5IMocNavlBK/8qLCKhn8tLoGrw48q3oP/og0nF0SUcRvq3n7daGY3Ghx+JhWfV8UidU1aVID8OaRxwN0/DQj/5LdgxBRKb+yboz0CSk8LYv3F4wItcMI41vqGxaE0Rs5JdbROH31RMn5WFHyqMgMbYgUhHNya8Amz29HmrBRKmx+mBolz765iXsHy9x+gBn5APpPsNdFfHtZfxBZKi87VI93F/ELdQCdV2iK+kFgki1cfuCPowQ9siyhOd+8us5wpYGpdif0kFkSk9UewlqvOWbZN4eRBKkzB5ow26xXHsv+LNvbGMovJSu+TwentZeyBLVDSLG7UrH5WHrRW9hLfiBxsrxBtz1VqhrGUZfHUtl2xNE5u2fHuaD/DVHVhX2BxH/+O/PtaFEYNDlA5AadmO6GD7Wb3/zFz4MGIljNQoiHk2MVrxwi71YpZJ5EDEUXKbuhi6zA0bGsNNscl0OdLRoDP8Dq64LmzFZ4PmWgwU3wUT/ie+iUJrX8YE8pGlVvHcRdmXJFlRDXy8mr1dw0vXH7g6ovWPJuc8ziGza7WowCj/7DUouQB9NvkK5C0GEXSkguB5uZezuWoXrZpiq114MItfXk3R+6NN8MMPJL4gcjaqmXoA3fOScgyGXpt3yIyg445k0BZXv7/Jdhct32I+v9Ud8fPgZ9UOCiHhG3aQFNJ471esA6ejMz+dDzglx5gn4xOT2g62hqI+3vAfc4K74ADUf6HJ5TCwC6t1Zba+Dgsnv/puDqbGJGxjCggjrE9u/HNDHZPKQamEQCRrZcHQvnGhRtzeHzsHaXlcgQ/HAlWcw2c42vh1+tf+aPAA3RtkW8xQFkdDNnPe3wi9L7VVKUC9721s3yNLs8yMXygdG/yqD1yj5s/VwOc2usqs3iBTVdvZ9g54HDtPNwlYP97pdfaiXzbmlF6DhcHBHMFQWOP03Dp5SGmmK/BJE1HYHziXDwnohkdtQKNbrEvfXICLpanU4EO6Ziw2NhvG/20quw+PRf1aLZ5BXdtMdNfAlY/mpN/CAn8DNLsij7TAk8zuIOO3/2BAIP89XL0RDji0FsumwokFqSXIxiGgudSirwvayGPe98M6d4qvRkKX3ttYQbPVv9f4F12fS3F+GvtmqWgK0FPJWoN5WDCYe3h+wDZIBY/6D0G1L+6PzcLgovtsbLi8d+hMEv7mJdI3CrZ2KC1NwH8M+3j9Qyag9dRMdBe/PWj5FaH54ZedOaL95zxECmydqUnjWUIi+4M9HQjBmvWjfVrh/j0fEPvjoeL3qGfikVvLIBfi8P9nfD450L3+Jg8xsQYypcBfNGqksWFmpF/INutIs98gwUsj3dSPLyrBj6KOwBvxb/DCBn4VCHudfqxSFea4+fVIwrEnp2gGolF63+RRs3/xO+zxsOj56wvvffccKhTLg1v2DurmQf4XPtQDGX7KOLYMrsgtVo1BSYPMWRVYKEbe4v2cnXDAzPUUgm3rpl/y1FHJE+zpbKby6NkqpEu58Wug5Cev+2IiLraMQT+uUg9vgIUqnlwIMfsfVV8lBIYsHKxjrYUPyEYWXsHfmhsIUNMx8XMW/kUKu78z6IgovZUes2wY/b9M47L2JQmry7MKDoOh0xP1wmCB22CUXip/zEXwCyWyzYSPkNNjq3QojfovbTMOfG020ubkppF7z02lB6K9y9vp/kM2JL8BfBvsKLKtDoOOb5PnLMOdz03geDPWp29IMpxTkbd/DgJd3rvdAGVXRriHIEJqz6QdkLpYwn4SSY6f3rZWlkFMVF8k2+CRDPFABuh/ve6wG9UUNGJ5rUsi83wWjJnji8e2kd1Dg7PDyHOw/9V+pqBaFnD0XtyAFZ21odyvAF2rPqI27KeTY85zmViisFsHTATs36ccuwpulHSbiOhSSzDSXLgN/6W0eUYZZuV/pa/dRyJXWLRbP4Zlvdrea4FxE/PB3aJwuJ8FoiHpgzri0Foo5rn3FBdN8yrNqD1DIuy9Z08/hWc2Evc2QeyU6/gds2/v7E+NBCrnHyqmwDgrUq4RugrR/D1XUm1IIzZ951kbYNpJ5vBVGbnKuHINFgVXrWMwoJGXi8okNMMjEoZoHrrNsdrl0mEJ6+rKfBUIxG3+hcJgyy3M5F/bKic49gY6HpUxf/bvus6OoDSZcfGBfZkshgbon6qugNyuf4BNoOySY9Anmq2r3/IF/nwir0R5DP+oyJTNDXhc2mVFXCrHuW06YgnymswsLUIFP2nbrKeQ3UyR2PzzMZ/nbDJLkmCNHIN1Zs0cswci3bZocBzQ6MnybN/hffRTPasJy1/ttNtCZRlHPEUbfqag5Bfk11GYolynEylbzbCRkSNQfuwp9VXJ7i+F4jEtzEzzmf9PgPXQP+vS8B/LSq8i1xVDIy3Sf4g7407BBuh9mfOfZ+hfqBxvqbY6lEL+/T56LwEMxGrpScFKglKkxDXPLblNsK/SuD+LqgHW355+yXsf/sP76rQrl1mX7aUMheWs6fag74vSoNRN9/SZKpwO+bClr+gR5Lq+lZ7tBIVVBYXGqcFVykk8b9kzb5erBRFfd7LZs9PcWYZlOqLVA+6gfOnyvomHPoZDS3IdPd0J3nd4Du+FOhjU9BrCz6ZQYzx3EYVa+XAjG7PlLxOFWOh02I7iJadtJH9jDq/SbAg+Y7A6JhLOCf/TEClDHi5SubfD76tpTitA392KpCTzyWj/KCz4+xswfCIlAa1EYnPTtS8x4SCGqtsMyt6DU2ZnGQngrKeJNO1Rpet4yDxtH2VxWoYa6NR1TJYXc/TwsOfeYQnQ8r71cht0qhifW1FCIHaOwjzQM4E2f3AfZe0NiTWHr2/PbD8P+kg8SabWoQ5Oclzfhpa0XT+ZDWervwZdQ73Tn9d/wbOCXnX/hx+e/u+jrKESilWM0F55IvhZVCPcnCkndh0eu8+l3Q+mXv17Mw/J3RSdXIRfX2TVM9chXxWftO09xzpwLQ8VQ7wVbSAVk9sxg+QBf13THTcPTTVmKi7Bxg9sH2gbUw7fgtaUt6LsY48pKOHlexL4e9pzPZO6HVeIDIfStFDLoPSzDBvVYpjo3tv6b95rnottR53tKBJKgKbP463T46NwCpR3q6ft5r3mHefeebF0LnbLZ3nHBLIcL1ikfUZdXCpmy4P75kYd3YPnqCbEWyLFnDQN9B/bzht9nhVVy7I4bIdPtPb2Z3RQyFKIZcxuq5e/SLoZ/z1EfvYcOqdKnGHooZDONqwA7vFpc2MoJZQKatfI/UUitY+RMCTRL2JdfCaUFQ/w6oH75aMVv2OXae+ovvOHavoWhH3W/EiL0aohCYoW4OtpgVtTdmE5YIZ3Wu+Yz6uVCwTNl+LYg1E8D7tt+QmkP/N5zK+z9MOqxdFG7F8q/t1z8DM8xnrnB8g3vRUdxXXn4o/PxsiqsSTtUpQ19Dlo2DvygkN0yHqEjsNImafcv+EDRTGXdKIWsP3NKWgZ6u9Z8V4ZPKjjvaMDgNMU38bD49uuINDhH67Q3Gz6nPvvTCPVE6u5NQM7JpNNzUGX9+W0rcMx+WbPjJ/oj/93yJ/iEFNcOQ1d2nQD2CfTJg9hldbhD8m6tDsyceBVgCD/Fe9/4NIW+kdtoPwyFRMvEfsJ7H/mnOKdx/cIB/l2Qm12iXwdeWliTbQhVwz5q5P7B98XelwyF8NjxmuZyuGeEfe8PKFCU68u3SCEf7n3VEYFn2KTZpOD+pb2x+cvIb9If61KYGlUuVgVvdHl//QZZU8tfcK5QyB2Nsjh+mKdZYSMG20u3V9ynpRKvtrvBj2GT0XaTZ9DOiMViFKYUTMwI01FJobn0H32Y6r+u0RgmMcwnWUG63MscU2uoxPPL9NAC3B12vJyGkUoCe4x+b4EJWsUq2pB6YD+TPqSpm+g8CHkvum2gZaUS7d9ZX5iheWf3ww3wcFeevCQcdDXqVIX+U/9pnYGC+54mZcKE6/Yut6G1CZNGMby/QY6FcSOVyJ0eHVoLi+QLqzfBOdkncxrwg4VjnR8cFXsjmg5/HBhfyoGGQ5wfC6C8rf9Jpk1UstHAkKyHnzIF+Xlg6rG5WSFocPnDW3E4JVxVKPvvumh2uArUuXrVXgvOOoVo6MGHsYE8B2GURsC0JfS0pLbYQp/uy/kn4c1XaSFn4ITovWMXofP3xp0BcAPfCFcY/OXFPhkNmQJVmpKg3eTJOxkwvzZg4xjctmduQoEbv8+f8GYnvHpM6c5uuHttD3UfvC0RbmsKnxxX23kYppr94rKHcqWFky5w7Vn35nNwx60d+d5QZi9dKAUumn6wi4TZ+UW74qB4TBRPKoz95DaTBQfTzNvyoPCaQ4Ul0DTNIKIS+qURx/p/+9ZoaTfCWvvQlf18VPKYa0+fOTyyg6XaBmY+e5/iCK/U5150gxJSPuae8BKNhYIfDNqrvD4EGtevaUqA9CIfLH5AYdfMz9qbqSTabc1TfajU55FlDK87fQuwgo33jx21gxpn+9SdIU2aHd9ZyBv5K8MLRsYG+AVCK3qOI+H/1t/uqsXCqJ8SHfGCVJI81PMwDS7tTUzJht3W03aTsKta55mcEPLj43BLFZbmR4Rpw8stZqx28L9GurpA+OWndVY4vBr2gBILGaP7Z3JEqESA+3hnAdzCOVJdDt+Jf+mcgiu/x75IiqJeKiNDDGD8fX9nExgs6rXfGtId4Jwr2op6PGDX9wD2NZQ21EDujpD1v+HzDv8D0uJUEr5N/7shPHSUps0MsjDUVxyBLyZ+2z6RopJ9shv1X8Gvw8ryb+FymHLdPLxaOMasug1xuxjscwQ65TA5OkB//QSjU/BiRaPGaxn0WXKRZDs8M5XM1Q23ikdmMMtSiWJaovt2OFxRf0QZhhyY0tOAhx809L9XoJJpGq+WXvj6jWzNF3iIU9CJTRH9Gj4oIg0ndrzdoASfOrxYVYfmBapcP3dSyQP9cOZZGOTc8/cvrGZRnmJQpxI32cRhdpjycb6bC4a9t/irCz9qcXKHwfiYN6wxkNcuYjUJWp0YGWbQoZJmrvYBdthj9KSbC4azV7wXgEWFwyVG8Lq7kK0fFOa0sQqBMdqZplfgjT9XFpj1qeTV9OTsBvjMy2aGF8rqDg6ZwIGdKg8jYfDnmftxcB93ZVkq/C7vYFS1j0oSN93a/wS+Ch8zfAUpD9n1F2CvEed9SUOc9zFvmQlsvxhN5w9Xo83pQqGCgjBdNBStbhQ8bYRzCI0IXYDHOdiF/WGm+zGJIhjQatD7FtK6l/Z1QfYMwf5BKGX7c8PrA5gXBrSc7bC2YfOmbiiwp0rwD9wig/l9kEr4iPacJPT4fG1BHh596pH8xpRKLL8cTH8HmVPkb/bA1IZftaxmVDKklMqqAXuMG9bvgR+Xp7iM4CGLa5dmXKlEZVwzZgme2DqeQ3+KSv5WXdqqDHP80p44wsyRuA43KDsbM+4JmepZCkLPoO/Z5BqiYcjS4Z4k6Erxz/gIS8s/+6u4U4nDRM71YzAm5Ph9J/i5RqzZHSpGPW+OO498GtaMpELu8kd02dC0cu+Tbrg4mdy30QPzyIvWUAk6T2yVOgobpgr2nIB96TuOn4YvZH/Ep1xEXbOXlGTBowm+LXlQufLujUFYac21vMEL/ysgx88Hd1w23ikCLYuNy2/4UIne9Nd3d2Dh56CZe3BHdm9yJ6y5zGqxCoN7vlxg8sV5PjZcWw+F3sZ3boHvWqkLEtDY5xKfPByJKx04Ds8V/zweBeecJILj4eVmp9w0uN2uNEU4EPMtxu2xJCxx3T4gD9O/SD60h1x8dmmJ0OWda236P9V9h3LhIkOTxBKVSnJ3qBykD0b8efIusMHxPvkdyvCM+ZG5o5D7LYvgSfh5uU73DAwYo/3BGE4lZ4PJxvVwuDl0Fw88vNg6qAqbS9aVHofXVq50u0B+2vX05+Ffr1HdjbGoK8tXHpthwXhhtigMpXra6sJb/Hl8J2CmYp3BaXiFrvfShX9r8RveXfFUYlG3pWAQ7uHI6/0Of+dnv+dIwPdIodGwInxsvJZnF/QoeW+gC/2+SiyUZyN/VQ3Kj6GjqeP5Z1Buy81Pv6Gh8q5ngjmo+40iNOKwtYJdUxbuFWX7XXUb79ON3kpPoU7TqMdrqCEaVDoN60dWFjbfwXNplKmJwV/Wrt7ScLupctWZYuQ5nGX5IgyN/Lo7EBJ3ykAJPFowVjUKy77zrEzDzN/7dJeg5vvhP95leP6RuN1UONe0OyoKKp5fO1kOc14czfoKK06Zj4xDTREXpnXlmAvZXOdUIcupvVXaMJDOn8YAdvNfzQ+twD4bjploSOOepnkN1kzNOD+EaS4RHgNwsWJf7Qjc3sHBPAkfbMkbf/uUSqr4W7W7odv0YsIQ3FXX1c3fgDw/8d95EDpfXYo+BMfUKIPH4Jns/QZXX1BJhhPXjRQ4xfxlJguqqljvfwr3Ocr/GYUmBTuNZ2B1q8HtJRj91naJ/iWVtJR4m7LD6PdCBTJQY9ZS5gS0vd9nFwXdT1s+jIeG9B/Yr8Pt2/pzvr5GnOPvL41D0hVrMQtdj8pxbHmD781YyUpb+ITtgVYILOP+k3IFbqDbM5UIB1uSDDPgGbowVaVWKjl92yFxF9ST1vulC+9vWW93EiaZlfBEQNH3jZ5X4VOVb20p8PzrowZsPejTmoQiTvjteusGAfjhCE/bIShs/ulFJNRlOb0tHroX0FxNg+bcDys5+/HdfO65kADMreoK+w82DrVOHoLZtTHeUdBs06+BeFh25JD+dVjw8Pgaoc9Ucu+pwVlx+LRGpVsWVlTsGLOGFrFrV4LhhV4NlyvwG6/Hu0S4pcYscH6KSu6Wnp5ZhS1Z0S7M03i/R5V/2gDnz/Sb8UHmAxteicDX4gaa2yDrZf+6o5DRk+dIPny+eK+tFMYHGO19BHMmOzJ456jk5Xgflwjc++17tBQMOPf14wmodNXt6014x7H96F3YukPzYxncxcEw2fGHSta7l5wagHVvjg+PQCcNh7csi6hjVQ5TaWiTuNCkBCPrPxc7QSfHU0tp0LYhyysHlor0ThVAbtkLAbIrmHNKiksqcGDXnLc2VL7634QrTDXQOpEE48/t+ZwBo9NNjt+GS/ppb7s4gsm1Jr2jQ5DXbnHkB5ST78zh2hhM+O15FQ2hTQVXnRls5+MxtIHG8yLFApuDSUFQodZW6Ce4660MJBdP5FvDNyxWTVHwc4GcbQKstV/36zrc9kusT0IomFRpx56Th5fyVxh2wqeay4dsYMO++A/h8PptLdercIhvejnl33W9wjvCWsHElfejqRR8z7NmWQHWdtyhcYLc1E7bFJj00YrlJpS07n+QD/PmDu8U1wkmn0ocR2RhQprnNVV4lk74rwNcsZQWS4OUiLD2bPj2x3BQAWRYluhV0AsmB79sjFaHHX/pNXXhUAB3uTu8qzfmFQ977DdLXoeRpcbdOXBYby+vxJFgsjB1rlMOdn/KSVaDu/QWzU7AIbfV9XFQTdSrLRXe5puJzYa07jIDcseCSVrarmw1WM9s4rgbnnUddDsBF5L4LkZAtZNOqnFwr8+jP6nQo0rUb/UM4qcVbMDsHkxOc37fxAHXvtfl04T0DX9Gz8OhPYVVvvAUt2N4CHwxMSS7fD6Y6CUJrq7xCCYDl+3a1kFRQeYhddhu2jHjBBlf2j4/CzOvjCV5w9SbATed44NJALt+xDm4foDb3QeWbk9myYQlheW3n0Aqf030a6g13eT5DrqF7TjGcCOYCOhvPLgWynvPanJDs9kXP3WgHavHszPQhjHjvhdk9GjODYLF45fCxx4Fk2b6i5d/w7uZ3rHL8OMMd55SNeIjNZjuBuVc1W5egEzbU24FwKXzf/PDIccul+Kr8ETX12c1sOEEZ+8PONP+cmAaxjdQvi7BQzp67xdrg0lchXwPfV0wsb4nMsQOE46pMajDSDd6SWe4RUxD7ty/68f9VHzgF4fxKzQN+P2JumsscDddatZG2HFbs1EFKgwe+HUEnnli/8cR6kv505+Bw0nPeYLgw5RpkUioJSaxPR6O5qtbVsDBmZHAbjhw0CrqM3yv2JI4BktrUv52t+B8An/XfYE57M4i4zDygoXbhlbEw2OwQhl6+4S/0oT2HEq9epAufWxSugf19WEX+w7onpcgoQU7pMWbL0CdFmvVHPj97YpZIRR2L3R/AM38m2mHZ5HnDHWFCUhxKTk+D63sFgJk54JJevfyqAv0P/N6swc8cy/d0A82hU2U//yDems3GJ6D8c13eWgWg4kYj7+e6uK/PmPgcoBHRR7qucFGZnefC7BcMN1hcRlzKOxHCv0K4nRDq4UdNiQZdalDFc2ao8fhSROLBFe4m3um0QM+n+FiosqGEPX5Z3aXoW+bT1UiXGNl1NIEv4tVZf+BBfP1i3RyIeTKzVZzdjh+g64nVDGE7CrO3hELFRP141Ng1YMxm5dQnfObxCzk0e4MWYHjOm0DTEoh5C9Xe4NvdQgZo48KDoXPthvoxMLCY+do6+HQQFt0L1TkfGs0DCsoney/oI+gFfPmhhDyxethixhsXi+YKANd+wSUXaBizMNPxZA3Jzi3Eo7OWbo+hXGtP7sEX+L+Zr1sCei7Ns9VAQYxUgVOw/uWUu/KYMKuX9cfQ5MTNY4v4Ln/HLpF34RgflXc2g6zN3OcU4E6lGbl8/BjfqRyATQ31qF5ANN30TfXQr2L9WtOM4aS+V/zyxfhzT7VuSDosm2krQxWBI3k/IRKLynp85AlSCSJlimUrJpe9fZhDSUqD1o9Q6DLlU1nY2CCr9/RCkixztg9BR3VdmguwbSYj2pr2ELJu75UTadtoSTA87HJOTifPOzoC6OjpJ4XQY/aVyyD8PWvvYKjcH/JG/nfUNpNo99XMZSslTkzHwpbqLc3XIX3h+kbPsIPo/leHEqh5KXh/jh+yKQ1e3crbGhqOB+pHkp2LK3EJcCEZzqlGTCCzud0Nwyz2cHKviuUCJt+kOKGzIO++4ShvELXdg7DUHLkbL0VPxQ0uxe8FX4/2XTYGvI/LVK4Ap2rfh29BvMs1COzIE1ak7rSwVCSaNnqogk/PepK1oeMoUEBvnChceVEMeRwtE2shOp3nj19ClsaBR6IOSCONSJTMvC1s6ysGizYeU/UHmY+sEy4AX/qN75oh+8cjen7II3qAPkGjbSqLtxMCCXn+W06CqDGhzVqFXDGuF34B7zldyVqY2IoufYmdEwAhsyGHZCA+wK45yWSQ4mf50kbRbjGoKZeAy67LQSGQfG2cOfnsLZtf3MrFCvhVeiGwokOX2Su4xz8tYZqcDJsS7kOZOcpDr8C42jEdZrg66dzdz/CryfaOAZhmoy7JLkRSmiPfUowhFMeFssWMI8IbYyCXLPpnS9gc8N5nbfQ46JxcQ8c4VXYrpcTSr6Re2kmMMREickGDivoSl+Fcq8WalvgjYo+6S7IdeVV2mdoWDTxPPI24pH6VTkR7nP/fCsT6o1LnmyEPht/b52C8//tTF6Cn0XCGRnvhBKFbXsbDhaEkrYf3TsOQ6UUr7uOUCpFzTsGJqpLvGmAHkqcWi3w/Gam8k4YFmAtJtgTSnY37H0sATP5dpkrwv5vgfudoZmOWettmOeX71QKGV8xrlbDgj0ZasL9oYRHJu39Nrhb+ob7DqjgKu91Cka9iw/Mgl+e/uIrgDaNlhUPYNt/iWFbP4eSuf6bYvJwoezhU3UoOn9M/SS8lDxueh3WO5pP3oLqhg2xJfCCruhf6W/I2/LuTBXo9MFVazd0vVtwwgte/fbiyU0Y1qHlUAjbPtfTP4RqHzrDOUdDCa/99DYhuMi+qU0ScjYfnAqAkUku11/Br2ZvIn6M/psTEdt/w6fnjNpX4AG/fcckptHPX2OYFaGJR0+5BuztNCnzh4nuh46+hEysm5jaoXZTb1kvFGmp2350Dv0Xq97jBDV96iLOQxv35rE70PtMoUkfZOONWvkG48fci6ZgE0t8s+0i4pIkEOAC3+0vlfGEZu5rs/MhB2dnyycYUPQ88DucP18tN/Nv7SkdfpY1jAQP0Or6wtqQwdVQ6K5fPFMC7T1OjvTAvxyxt4ah6Gid/STkH7SVumUaRjrFvwqUwKZPHhuq4TIDK8ML6JVxd74NklumYz3QUYBuYBh+Z3j8bvLfPlv/l0vQp3lvNaNZGLFi5L3HAatLp7MF4N2mj9ckoKyGtaciNFUzctaECvtvTRbAh6x3E3nNw0jR/oORYnB1eclfFoZd9lv9aBlGRJw15wahXiXTzzH417fnyxw0Kq/ooT2Ec9mmtbPDfr+wVzxQYZ1vvSikfeX1UAZ27PYvVoM+cpdv6cJvZZvmS+HijZgFIaswcpzrwKQUtFjh+q4M+48OD2hDJvm6TkPYeSmrzRJaKUc1Hodx5pQiN3jlj+8tL2jKFZhBhT9yo5Kiof7Gxp9SR8LIAbmBEWVo9Gx1SBs2iPDcLYbTb4JS+W3CCLuUWaI4/LSyPVYBrhTe8zA4hrzR/D5rDivbdp85Bv/4DVk/hK842mTW2oWREfpiaV44eC5RSgx+qggftXEII89XpkadoOiLk2PnoURV68R9eI7CsTgHme7OLNI6hpF44/4ldjj3ZGuxhxPyrFBVGgAfi5k/iIRh05zPHsBAEab2QbgjfeLDGFy81t81B8dc6b8fYgwnsvRjzg5ww43ekTP/1nWbXPJgTEKN9UdYrc3UPQgnJo4cHocXjLn9tUXDia/zIMd+SJt6P+8Q/FV/UjoDRsqnFvXDtblDOqPwuqxy9ywU7X/OvUc8nAitfVRiDH9aPTSwgYKOJwduwlJLu8tfoe7Ua7FJKHZXs3YJRobPGftsCycSpgrjoZBp18XIOHjXoFmxAy44aeazSIeT128m9myCVgfvDgnDgqnTgdvh0GjngElgOGF+uqPuKPyzlJHhAn+yyc7mwqDsVvl++FApc/0olJe+ODEL397tlduZE07WKJRt2wsFd8VtNYW2KglMaVB71pn5MzyW30A/AX/2i6/+gZ+8S+cNCsJJseL4ggXc6qWweBwuW6XR3YW7n11lHYZlAfrsU/BgA/O6ZTgVLT5pU47fYW6Zd4bHNgWsesKQ8QyhW1CzgFtvEJ61FT84DiOytQ8twJl1M0sv3yHeH10E30Na/e9aA1D+pd6L9e/Dib9R1hkjuONS0FVrqH7QtewE9PugIxXPGkG2mxy8lAnV8xxf3IXfrvGv9ECezNowXrYIwhK548N/sOVgpagCjJO7P2SyOYK89jymYQv7bnKmuMJQSUXbPPiJ56JXF3xpF9P+Fa7ElWyfgrdYxrOefY4g/cKPM97C9raktE/wnc/JGI4vEYSXfh2d/pd/9+mvmkPb/Mt/j8MEzuo9JtuiyKy6uskxaPffS5vTUO0yQ84TOGDj58ApHUX2/HfTXQQ6l7z1lYMOHRJ77RWjCFfsKauz0Gr9I9cAyO48/eIZrNWY28GrFEU+K78zEId75x/ZKMOT5S0ll9SjSIlp56swKNAwPpQIjUqr9JrhQqCH7cZdUaRYcMVLGPLFXouThaZ5dA/YLK8QkXcv0/hhQW9qkDQ0fejG4wbTrPbmFcAAtaSYali7MOn5Bv4eNh68ZRZNtoSa366A65mcTr2Ej1ez92w2jyY0XE+HA2GCZXjhVdjmf+T8TehbnaZZcSSaTBg0sryEt57Td3RAb96NH7bZRBOePVnRgVBhLujwVWiffFb8Jnyc0HbN9nccMa18FO8CfSLvxXjC3Bpu3wJooJjh2gE5ny+dHIIs9E4O49DCLdmNQyie1NEIxwlAv0sPHkjAbmFPfQv4taCsiwI3bchfvgIlrO6KpsCws6tfA6zjifTtFzpR8Adjys0kOK9vxNsA+Qus435BvfTYicV/60dtRoyH40meSMkir0M8ka8bsf8PKidKv5aDWoKFTrYwNZa17zK87HBfNxlGnXUuzIYqzJlenktJpJqr91owNPaVqoiHm2MYlVph8qNb7Xx/k8jAjeQpSajen8qhBl9PUtYeWU0ifI/m5F1hzKC/hTcsUN355QH0kZuxmIb299l9aGmuEZsUlcwNMOLjSpiZQwrRNs4yOQFXuC34vWDVnmm9WuiXbHGBwTGFTIs80eaGt/9qs0nCxInKnNOrKYQxpU0kCI5l/70ZD/3zw2/0wkK2wsytNKnEPCFVUA1W+qdnGsLzyvurr5mnkhK+Nen50HHhg99j6K08ucpokUqSN7qFmcFzNTTOJyGnfZGBNyQ2xwMcelNJ+yGW5YuwV/e1fxT8Hx+CQdE= + + + + + + eJzVXX1cz9ce/4piShYmGjlNKxFlRTXZTk1y3SIaDcWXGYawBzHuOEOSMTaTGeOYKN1m6Y7l+XBpnllNmnk4njaUnqRE6s75LS/RbfX+2cu9n39+//w+33O+n/M5n+fP56tptQYyNLmBT+3RND13j8l9PF7UPZ8C+MTVXeFrUcsu1QRf/Gha7/7/dTbvMrKevj+zDvKedEHPC8h62qnz1xE8cXBKMYJHx0y8jeCRgrAiaL03itR6fH2QF0TXVfYFtVlX2revEZ88hvfqVsU3dNPz7SE+Tzur3ccTl7RmCL7M+twMWveSpVqXDVwPnY9WFH4LwaNOhRcRPFJCbiB44uzkKwrvxoZGCJ0ee56waIc8Rww59Ax0TnlW9sbsW16cX0Z//2W3g6H15fYcSB7KwRa/IXjUu+mvCN5fBXRt+qvQuf3yemcIL2efhuARhzSIbnS8hS2yHs/vlo2sx9snmkDvt7KFp5Kzvi2gdStAWGRfvI9PZy8m1e1Djm2Uh6yju8Z0Mea+6n0ntoHuqf83Hsp+ydCcIPoe+sdrEL8e3K70Hk1o0MSo987wKaQAHrU7dxfBqwDmngDd0wqQfW9aKT16KN0ovqQBLV+C6O/vrOw5eX6ousc09hkDHRNeU/qSFZtA9vOD5ydvaAvx04U3IXuKbJn5HLIeW9v2CrIe03ZCfCs/r5MDrXd6tBVET8dYaD25JRI6PxljAukT3Skb8oPEcGtMf2V9CfmXYmCd5hBd6l+F7pN0izX4MWH9of1WAO0xDlqfnX9F+Yt01ko7pSc6pmRBz+lYUlYdnoyOu4c8V5+7DpKfxHoP5IfIhNr5h4+CLhNfMEpvxEWqc5Sh8c8a8xwx8gZkp/DgQOic+I4rkF1vLOjp/h89Cf/trwJiaTb2iewvvAHEV3JAyTUK4Ik88Xej+M8lvyG0X/e9im/5hDLHh/HZtXhID8hN8X5G0X/rFUyuf70RukcVIM76KfuTWu/2geyC2I0YvZI/tqpM9whXyA+8U6r0CMtoB/GfTjcou4bd0u88jE/2roDiNXqGOWQH0vJN6vz5z3Ux/Tp5PBZH+z8BUTxwJmRnjT5dSgE86RMF6RlW5A3JYXHyk2rtD7LCqlq757H/H5uu4hxiVS/TqvajXwoPgO770hSMLqvHQ/YOzzOvNk7yX8HyRbVPZusOyQVaPDsXwdPyh2FyPGkQZEdq7nZQ3ELknYXifLpdG8jeI34LoXtYU2CbAyD9IYaeuUp//5UdukP4ZJ4Ldm5/AC0thPxAvtxNyQumZ0H5F77kXI38ZB44FvOL7TsY7vv2+ZX0ak2BhR0rQfDE3PX1IL7WZ2D3/YUJVxE83foCZLfJ7y2g86Yl7pif184Fki9kjj0U1+L9DmB+eFRvKB9Nx16H+IVN6wXtU7/ZX8XXyY+Loby7fssXsvNInFnVerurneILuucH7H1yVlRpX/wZ0Ned1Xr69OWG+OCmPVidRURDS7V/n1QwLtW5WrtEt3I0Tm+FnVT3VQ7YGgjpJ5cio+L6jwKdENLt4X3oF5yhe8qGbVX7kruu2jyMz6e+X06R571vq+wRPebIixCdRpardWlqNBTfpLvTVR6Djm2v/GGeEgnVqbCcWS0gObvrmpKz3Osrg736sugA6bHPV1TyE0h0T2w/PoGQPuSrjmL2gp87pGe05AlYPiM1SPGJntAGi0OvcYf0DUk5itUjnc/G6k/OBFbvr+0nkH/EG+uQ3hR5UyB7Sfq3xuyCMx2g9yNeTTG5y4Mx/6hfLOQHPIBerTF/rrQJ5F+TYzOqpQ/bMaRW8YpHgbvF2ED0CPwZ0j8P1r0aPeBJxNF5mEsPY55D9uUoPpKT/SD7Q+SW1ajOhQTduHn/+fSwh7LDqBOvC+nPjHnQPWPr9JZG0TsgWOXr+R5/4+oMIoZZ12YfLHwW5E+xnUVKX/GLJorubOdNQ92v8/4a2RvU9wJU10B95zSF5LWTHaQfCU2p0ftI7ojVFSTlQ/F5sT1L2fsiZovS/yQ+FKoXIF/kqntJeQ8orsk2jYLiG3/63D6JQRBf3hhvyIetnGagx8kPsLrDW8EQv/DESSqPp5tON5xPvVBIL+m7Rio7iTc6BtlLculP5hD9VkSr8yQ3q64vpPW2YPV8K/IgemrnukD2i4y/C8WlqJbprN7bwQfzmzqNqw/lcXtlQ/6e9HkT22fvT7F4h2l/f2ifmUs9oXuQ2dYBwntrKFSnTU8cwvKPm3XIzhN7zKB7KvMnQOeuN/GE3o9N6wPh6Vuca5VXkDGWkB4SxaaQnNRGfID5zU5mkJ2o2YZ7Q+cdWA+6B+L5SUqey51atfed954B2SF0n4uiO73bFJInZLQHVucWhOVhySfLIb+dzbOB+ESM6AzRRav7k7IbdJfdUF9BBdCZPWvlD1SA/uEEaF325kdQf5soHwzVP4nl3picP2VnB+V1PiurkZ4WzaOMqgeT6aFQf4eYutoDOu+CAYb85uRZyt4ii/whf5YWDVH+hEjrht3PGzOh+A+rPxOKD8sDYZC9VgH8m1ILiN4WLSF5y88EY3yxdQFWz2He32DXrInD6l5yVleStyJuK1bnMaAQ4kfWx0vFC1jBaszuCVxliHMkvIzFQxv3uVkTPLZoERSvkqUlkPwTu37D7J7cQki+s4NT/wbxe1BQtXFDPf8wVlc1J7NqfkhaptYjci5E1wf7+tYL6h9j3csgPhWnxkJ5LjbPGYr/0aljjKr7f1KgH35rjLKTfmjxROqy2KjbIUbFcb/JqvK+k9XLukP3tFOp6gtkudGqr12kJUDnTB38lBwnx3xrJI8eBelnY8hHtAmE5BSzaY7VJS0SkH/AAgKq5Gv2YQLEJ3RlX8jfJkWGvkKdZVW5ri4FFLfVXhwP6UPZcHaN5Jqgllh8wW0Wlu/6A6TN11C+Tc4pgfiaBn8M9b2Kwm2YvO3jDulPurat5RPJ5314G6u7m3IAit+JE5aOVeIdOQndazHzaGNoH4k5yv5l9dOheJu2bDTWV92xHoXu6TV7g9z4ro4bFFcxdVBxN+60BKpDkmHtoPflBaZQvkUz8+0IvWeD9ZC/KJulYHmMVicg/mPHmC+E17RxJTzdrE2N+IGcb4HFuSLWOUP7PFMO9duxhud7GeV/e5x6pRJ+yHXofCpAZpV3NQafyQaYPncYDs3DYd4plewA2qKpkhsiegMWR7mYBvW56995QfepAuQRj9bQPX61vvLP9YPboXOn+xtjft62ACiuK0PWQXQSJfZQ3QONCsHm4NTxhfKu7HRXaG4L2dRVV3hzkyD76AG8cx2qG6DhFtD8Enk8AuI7cvhtrF7NbQNWl7DgDiaXDnlgfUEdLaF8HPO+DNkdjHWD6m/o5iQo/suKbkF1zdI6xdDPeDwHqxf79a6ij+hpjc03eskG4gPmNh/zw9sKqG+K7ztoVB0p37FQ0UkWT4XiFWIcNpePXx+E9W/0/RKrezVfD9VfMREH+b2kDOuLkL1bYfk9k39ieaR727D+uQxLTP7EXoPOXXdMx+hp9TaWP+o9H5qPqZmeguJmPGYSdv/9hkN2EjNLgvS4SJkM+clkmH2t+jakVTPonmtWa9U9kPvrQvl89q+VEH/Sf3tU2q8ctLjac+HRq7H41rnXoPgdS1qO5SXXvATJTb6wHVS/8wA/4VtoDqn89j2szuGTXCieyl44htHVJxmyp2jLtiMhvo5tbdS8EBafCPVJ0OhyLJ9zMxGbE1rHvNp4s7h9DrLPCBsMxfl530FQ/Fvu88b6/HkqJh++S4HkHj80GfPTI5tj/b+FyyG5Kfe4gvGEryA7gEyZhtnFw2MwunimQX6kPmIxFE+T7c2gOJR4LwfrSwlxxPxPWw7pL7J2L2SPSfO2mB2e2RC7t70ssTztc0sxOyd2BEQX4TgPsjfpSgdoPqsWuxnqE+C3OmP590ZzWkFywjUI60cq6IfVJyxpANXFyaxZkP+l266A7CrqnQHZfyQiFIqH6K5zFF3I/HQsPtZgIXTvZfAuVR9PJvYz/A4dBMWr+KohSt9IP1uj5gM+bZA/Tlr2JPL3//Nw6Q1DvWXo3HlP5X3vtnu3unX1c1nYvKKvRve//1x6ZyX2nZAWk9Rccnl1C6Rn6Pzeqs6YRhPM3zGbiM2BdNpm1Fz4x2BxvFH5Xm3MRSg/TT591wXS03ndK/UJkKRRWJ1u6ihovof2+sdYHjf7MGRXisT+kL7XptioOhf6yh3s+yx736tU18BczmLzRazSID1D83dg9vT1Jdj3GhYMhvhBnkiC7Cp9fCT23amTKdi8lvNzIXpKk+5QPwUvjsDoYt4Fy8NmVz0vTNeTsbrJIlfM/59TDvUx0ePhtdqnDEhWdhiLfQ6bs3UjQ50P72AOne8DCE/A6s4HOkDxAC0iHuIPtnEQlH/6M5CfZULzueWZJOj7b3z3O1XGl8TC6VCdEL2YD/lNeloPiJ78wnEwvtIHij+wjhzKz9Bid6yPZ/IQrE7TdDYkn/VmO7G4r1MXyG4mxRuxfoeoGZC/S+4uwOzzk7a1iv9x25nYPbjuh82h1SgW/+n3NRRfltsKsHk7v7yD9ZFn52B9B5vTIH1EvLD6Yf5sGFbHf88TmwcWEgPdA9H1BDRHmtUNheYU8IVxUB+avNcVivtp3QdDfhX9AuzTHNIJy/u55GLzCc3KMDv08AGIz0h6korbijZHIX7TvQuxPNaihdD3Yvk9T6zOOSIR6x9ZtR6bfxeN5b+442jITqadQiD5JPeHQnEi9u5ATI6KXlgf+csRqj6ZmkVh/dxF8nlIbpxah9VddtsF3WN5fIRR9fh/FZDIIzOeSlyY+EY8jXVFqvlwSH7bXYbmboo6HaC6Yv5DKjafLet7KF+n3w2A5nWIZk0g+StcHY36brUYVrM5Do8C16Ox+TtdemJ2TeRlzM6/Yon5dfHjoHoQcW4NhMfcNkDf0SaFBKrP0Fu/jem1JBPsHN7KugStt7sRFv+sPwKbi/Lbbex7aR8kQ+fH3cswuoxaAn3niXRzgOQh9WwF0YUcMce+R2VSCO1TP/2P2p/DfwD7ygTQ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eJwlz89rE0EYxvEhEfTgqV5sFd3uetAcikRBpCBjstCTQisFfxC77lbaRqs1tmqjljXZqqmCVkFQKGzSFCSCSBAqPW0lIDkUseDBgrBN+w+4XjxKvnP68D7zzvvOCCG0Z+YFKYQIZ4soGp5yKH6xrTbvXWoblHZk2lqnNi+TH9At7DPQWk0pnbTKvzkoBssox2NXyOd0DBYcm73LRXQXhUP/dAHdvir6ww2VT20rK61h7ndWr1L/3EJ58NAI80+a6O43RqnPOGOcW28x6Ipn2dusYNA0r7EnMq4zbzGF7loa/cBW+YtR5e4xtJZaKPUt1W+vjrPvu3mD+d0eyocDE+w5vIny9Z9b9NdjOeZVU7eZt25j8DuH4WD/JMZTU/R/6UfrjX6Hd1USysRfDE/E73Leuwe12g+UQxvomy1089l7nO9tYbAvUvXR2DT9OwdQK0VoPe/I05fMobtQuM++peQD6sJX9OeNGf5TPobBhzRqa+cwXC675Jn8I/XvJmq/Ogvk690o/x1RtVHBsKeGoqeu6uMr6rxxusjeXZGHN1/N8t7MO+XLjsfcK3ahNaMrcwkMJpPolyvo+jUM39dRflxReXLjCY7YT3nv2SwGXoTi86cS+fneOfkf5SXXww== + + + + + + eJwlkl1IU3EYxv99eFHJSChilnRWsJtANAoTZP0Ho6+LIPzoooLjCozsphC67IBgF0UIRYUKnraZqWXZmpkinVWmhbFKqVXU/qQOTVawILL1eX7n6uE57/s+z/O+5y+EMI/PJ6UQQu3SroO/62/baHl7b8D9tUPgmdZrNpqytJ26a6HDRnHInQZ7JhI2GsUb+uBXymds1Js6TPj+2BP45R39NmqR0o/ohcu6wFHfHerbnXnL9y3P/x9lYCBjc/ln/CFz+e6r9H14zZzKtZBbnqt4Rd1fPUw92HeT+rGqKPq/gsyp4WXsY71Msqc+GeW7Wechv3Z+Ic4eh5vJKfKnnT1dEfJpJ06iby69dAs+GBpF15UNMVey4gU87sdf3j87Tr+3IEJ/w7Me0K26qafa8BeFBYPMB96jr9Uf4N56SyX+2vq/6FkjjfwX/Yt3BPx6BD8tFZ6Al20bAz/Fnbsu/tyLT2snfiqv6C5+VQ3saR59GuN7ZiX76Ml9YXzUTCd9TVnyGjVt3U6ODHc2lp8mn9iYw8cI+thP1qx27je3yblTbAl6cioHiqJKdNXad4/pu7D5Hr47TzFv9lfwX0T7bnJqtWnnXYVGJ+HVW5w8zevQU3sbZ+kvv0gOORQdABM/0NNXebiP8ej7NHslinlPYo/Hwu9gyul7Pv8G/QfpOeZ/BqhrdYvIod6uIafcmuPORkkh78hUs8xbU9ku+Q9ezvvn + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eJwU1nc81V8YB/Ay8wstsklmykgk+5ukzLIyQ8kImRX3XhfZI7JKKBWV2RAVSkJlpxDZm4hkF8nv01/v17m+vuec5zzPc74J+QE/teV8iTN2ya+MYA3bk3AruPyuMJjdz5dgWnO7yA+3G0k6ikGVQu5tp+Emjj0NUbCyVrQ8EWam7HmSDqO4bEfcqb7ERcM9nb4wN+dXUxBMkTW68QhSD183GYa22zK1p+DbDcVqi7Dh65pxTLAvURVdrJsM1Ww8j9yGNL7O3PVQSa91cFOIL3G09UDVPjg7pFUmD13YbJ+pQTHlRuHocF9ig2ojfxLkP/uZ8xaMMePa+BbeOyE3MgVV2936FuHxoLyvf6Gl0IWVqGhfQlDl5VIinCYxzKfD9K7+gVr4zcSmeRF2SYw1/IV/RXxqGWN8iQsHT+n5XfUlnli80r4CmzJFjkVDQQ0a1cdwgu3w/m7o2dknNQLXqq/sm4azA04vrif6EtEP9V9mwLzkQyXZsCRCvmLs39hhwwfeJF/Cyiy6URte0eloMoIBjnuareCd1tEJmxRfYvRx1LQTbCqWnfWEqubXGbNhsPwWnjYorLLE3wtTLgztHoOC/t7vl9J8ifZMkYZ1+Gax99OmdIz3vp+Wh8GXztFbwmMhJzfbQ9fyw9vcILvH+02Nt3yJ1/fDtnyBjoy6O/v+aZK8n+a2L/FSOEtfFPLxpZhIw3yNeKtD8P2cwe2qTF+io5Sc3QAjn+YXtsFGp6yuX1DlW8El4SxfQu4qc5AknLf1ij4IO068fGMPy5MfXU2E6w9PpqRDpYlf9+7DxATxppGHiH9YUec0fJF3ZGwJHtI9KyKc7Uu4k6zMj8OpWAEHQ0jb9s3LEq6aRE3b5fgSl71/rJyHm6rMN/nAUvUy3bvw++fGa03QT9vzdjvUmefM74cCWamln/N8CRYHh9ouKGx5sGMYhgilCm7L9yWE/Fr4XKFu3oMdmfDTpond+bA7bb9sMUw+/G5x5BnWLXqA6QfU0sjmXYZBbfkuPEW+hPGg6Vt1KDD5q/U4rNlzb9wQJgzNKV8r8yVIVnXGN6Ef6wPXe/ByubsP/SvEmXeA/ShUaM/RMoNpJ+ds7KAL/WHf8/DRQvI1b8id9jP68Rtf4nCTyIOX8KSKXcVb2HMiQHwUsj2XT2Sq8CUW1O8UbIdDDKw1PDBanqqtVYV6sKh2OAEbX7EGm8OLeZ7z/rDrtHzHexjcXn+Pvhr5OrHgfBR+ey381g4+tGTpPQ+tD67+9oZ1YsZLdfXIU+9AjlY4s/b0UA/MilnuY2pAHg/UhSlARWX5bAKydzyo1Yb2xTyTRlC292VCEEx5Y6/0GA647bB+CRusa6lvoVeunEZ6C9apMuh0H3azJcU+gnf36xS9gLuTGDor4FnF2r+10En4mnAL3M9wWqcb1pKlPEeg7/0/N0Va0Wck20POwfz8pdwLkN+D99NleHdw4VUgPCQtMhQJxystNyXCZ6nXpdLh1WCpJpGviLsr85IUbE6b4T8E23lqHK9At5S0ykpYotwyWQ/dxbawtcFHQTGO2V1YJ113/FPY1Sz9qhTmfn55rg9+f5HKStvtS9x/V18iBjsOvBDWg+4fz50whfGFnGQb+EB8vSm2F//3euX3DaiUtipyF/5u85DqgEGnnmZx9CEOyqvNuyCzi+6fPfDvKQ/B7ElfYmT8l8lTKFobEVkKjT7dix6H9LavtQW+I85X6n+ZwvZfJfts4UhFgZ0zvNP+INkLZqr63kybQ9zaUj5lzf07r/JNj+Azxm2WI7Buc/KI8Dzql5vX0wH6+XHxJcHdrXWmtyDflcC4B9Bccmnm5AruIUrMPks4tkv0vD105w2PeQE/Vprc5F31JeQTv+8xgkNmO52s4KmLWvfPwcmukFhHGj9iy5EPHz2gID3rVhIUFrQyDIYDEmmdpfD+dNWVPzBsybKantaPSLb4RbcFft2ZrsUJn23nuqYFf5Y2j3rBi+aPxCjQyjD+fCjMv++XHwsbskPNfP/zI6IXvG4HwU8Z54ajoJV2WEQl7BE2EPgD3eLDHeg3+xGvLd7ls8LmIMY5DlhAf/KQIDTg23zzBPzp0PWLCv3nT6tHQJr+sbB46MCraH1xux9xyeDdQypMGzSZDYeHvP0cn0MOu3deS5DNSvs2zw4/Yr+9/Ddh+LRR9IAUHKzmqiNguiEPmw6sIXbbGsOBzOvtV2AI/ZTBU/hARCqtFJ7PvjRaBXfxsO1j5vQj+n16SOzwoExeDT+kfphOOwXPHBUQDIObH0t6xMEr5MPlKTD/xwZdIR4/gpSYlLYPqqfvnZSHZ59WilvBlcLjjEmQUyuwfQx6HzZyYuf1I2r3er3khyGU64zi0OhzQfHn3X7E351Fm7rhjvdvrEfg1wShR0xCfkTg2ck1KUhTLmp0CHIHOT88DCMyHyw7wteeNHqe8Hb2ubskKJkmNJcBLweIpjbBpcY30+3wRKi1xgB0YdTZwyPuRxzmORMkDPtTqR2S8Kjp6Rhr+LAkioiBPz8OpiRD+ZPqM7dh1r5mO2dZP+LX+YFyL/h85zI3BW4Wjrx2F+6TJtN9gLo1lWea4dpH1oqvUFSylPQdPgzZ2bEA67RJcn8hTYVSntABP+KlgMsubWjQukY1gs+WbnRbwfdRtDIccn5EZQ9r3C44ekdgag9Mp3lfZQ7FwiVVAmBz/sW0CPj5cOWveOgYFhrfq+RHmPwNmBuDpMkAk5+w+9gnNQFlnHsy6aoZNP5W9sMO5j7ZaOgCtUi73yVo+BGLvTck0qFh6daE+/DzUnVCKwzy+yspfgR5Plu6dApWsd87bQf5C2PfnYdh1YF7feBvPd9Ef5izlHE9H9oZb1YagXXemvem4clUW7UdmqiLSEtNDRhtWJ+vCzsS1HeYwsuBV1ifGPkR4rtNA0pgg4bUj0pobl0SuwJr9V5z7zH2Izad6oiWhV69yyvKsPV24uMX8CDLBoG3kGbV+1odPDmdIktj4kdEXeYmK0OJz22TmtAzL9nKAO4Y/LCXx9yPEIqsyhCGN55Ub5OCOYbrvcaQ/dIMbwi0uycWfxUSBg60N2Ahi5hmmSXym5xbUg13OO+XbIKbM9q+0Vv5EXSC5IdqkPGBNs9x2JXHH28IfY/zv3Q77UfMtcpKXoaKQ3pZgTBbYYryAEo16Zg2QPtLNxra4LW744f74FeJrxvenvUjXBcZyHVQ7qjyfAtszUwypLH3I6zfnLlhBrVGpjziobbI9YlUOPBdwz4LstxbqW6BPlF1qj0wevn2y1EoOSF6Z/M5P8JM126jMtSZd6VoQn5B6qI+3NG6HsbvjLhXnKARh7vlHgTsh+pGsp5mcHZ47CwVNvK594dD3/4Vq3jYZbDhTIe3H8HHkTA8AAddxRwnYfsJl3kuHz9iyHnmpzbUrq3yMYaOxelL1tDt9S/rarIf0fRNfKQRaj2wcW2HvbOpc/1QYTW3WJ7iR7zi4U1IhvKPP3BmQPHPl+9mQ/9Al79c/n4Ez8rZcCHoQX+GVRJS7527cRBqf7zAT8CvMf4PtaFUV7yUMTxRmvfCGqrvqVdzhLQSMx884J1XXCdIkHPDdFYI9CravS8WPl0+XXwDdjRmqNyFj+OV3zUH+xH13fwnO2FOGWPPENSXXHKagu5XZWsPhaD/qnt/JkP62dLTofDSQcbJWLiyxfJyCkylPqO5B00Ct17Lg7LsF3mK4UH13uxy6BBDkauBVb0zbz/9e+7def0uyKc+0TkM+YdTHSvD/IjQVfmFekif23GlDdrJ3ihZgYOPue/vDUf9yyzsl4dbjrVWqEEar/Px7dG4V6zWdg3Aup4bhRPw06K8xjxM3PyrRj0G/SLyZ2ky/NnJ+qwDalYpHhmEfhoubZPQe2QjqTQR9wTbAdZqmNh/PqsRPplqjv0Dj1PlFbWT0K+5ZZ/n/nNe8Oki3C7OrLUOuX+tdm9K9iNkOlOPfU7zI0rsIga74EI4mTICjZn7dPen+xHf0jy++cAPj18HU6GrfWL4o3+/Z43unoVsjZTyFUhK4jCnu4X6kFGKMrmNvHC6K2wDn6syv3WCIk2UuhQYodraWgPz5v09PsNe7X2bu+H8nuYTw5l4b9jlH1PwSKhQ7BIkVP1HFLOQ7yl03GlQbODYxV64VnFlxzjM16h89hPKOzMYrcCHRAfdfzl+xDaRkIc7oPJjueN8sFbjQPMRWLkh4o4HJJm6HiZB/hOmw8HQ4POzmO95fgTzp83Si7D7okvLX/hC8I6ORr4fMRxY9voWHNTWHByA3XtlwiahebHgngXopH9t0vyRH8GVZnbtLPwdKyLnBsv4gtxuwfyEigeN8MXzBp12KHyld6YfVl7g63j9DHnVxBr4Ae5qpxf7BG8vSHpsKEKdKpRuVIYfjmimeMO4Wv3BTBjaY3WtDzKJLCt8g684bg7Mwr7UD92rL/0IpfKGcPoS1MHV9v1boNaTM1HqMHfkQ9wNaLR187cPMN0kIunTv/FRJvUueNj80DTbK/TLFtY0fljwe1JLHObZJK8YwJqx8seX4GnxJqtAmMYxtCkK1nm+/XaiHPVFO3bDAj46uu2oPbSvVStIguSe2qZJGBj27iDPGz9i3e3MqDC0oaVLloI1Hj7PcyvxfdAp6lgENef7d5bDAmKtcxgm9Yff/q/Kj/gu5WPABn9KOazzwUZmNbsnkI07ZlspPPW1t6oKDv/4pDgPKWfqNnBX4777z/SZELx1bsxeEi4pcn6/3YLv2ruVD7LhrTeedoVQQ1iWYQjqTIY82t7qR5guejnzwtESByFR+L1Xo+HiEPrWU9VrAbD0sJpxJNxvmiJWCsdzjA8NwPcvY/9MwEvhTW/nod5y2vDhYT9iZxhrji7sbYlwM4X6jl8Z42FlRnT/W1gzffx+PaRbYz7fNvzve7hxVvcb+jbXoVJTmLQhN8gWtsg9zAiHyXtkyh9Bl7G20JewwiFQrxK2Pd0irfrdj5igHPylBQv+s688CbX1bj65Amcia51fQ6WjSrIfoPv7wtXmfyZlxK6s4P6wYrajW8U9MBMoywobJCL95aFh3dwHa6gSlJbqCGN1fUZiod1kvfRzeOTDQ5oKePlC5JdaaF/XecpjDfXnUyZBWvsX17t/g2F1+UWDPOh2KFSlHb7sydg6APX0K0Ym4M2yTXtf0pCI7Vp0NJWQ8y59Zz3sehwxTE9LItZUp+LVYctORWdtePFNjLoxHB6zPMO6iUR4aQYoc8L/fLLZd8PiFBcWJ0gWcN1+He6Z7p/KgEJXLWtyIMOy7JldLCRiS8kpNQlI1QvikYN+Ags6HvCGRZF5MZyPP71xFNp2Lvb9gLGLSa9/wTTGzVmU7SSCV9UiJAwGH39kfw1mc+16WA8vlRUlM+wgEZrM7L8UYLNwy9fDMHnH9VLdf+q+4qPCbDeyfQm86LPpWz88XyteNwEn5g3y5mGngPvWTxwk4oLe0HwntDW07hiG36WL9glwkoh0oZN3TkJvg60hlnDYsN3xHMzZycBHz0MiArNtabZA+e0V45zQeWr+rA6kK1bsp8DL/p3vwuA6f2DeNTh6MW7sy24SoXY64lM/5BUKL5uAVasdejxCJGJBtr5fD+YEMNWfgjtzDIrtII2wLuNT2Mr1frYUxk1r9lTD2fGA8O+Qg5Pg4xMmEVMpK4xisG+xbE4GlgSo06cpYR+yumtZkL/ZevERfBbI8rEf5hk5a4gpkwj6g2/5zsB+Lo2drvDlWB3rJaizo7f1HXxl+3qcTYVE7M/JGeCHvzvTOsVhTaw+uU6DRNx5cMC3FU7nClzshWQJ4bNcR0jE4b4Qc0t4kLEoMAHq2yt4NsG9vGq7dmiSiJs1b7j2wxt7yRzK8Jm/MvtRmOSsP1yvg3yznB9pg2XKd8b64NYS45mtuji3UfJfO2jIrPYwDjpRjxTVwwG/50Kb9UiEJ5lLlB02uYWIC8DH10souvokQrisK8AU/m2mCbaFJdf74iKgwsTuW0+gl3/QnVKotnEksxrqK8o+GoSpoY+efocJlVLFi5Aq6lHFZ0AiUrysPh+F56W2fzkB2Xo/frWAinWii0lGJEJwwHX1NpycfLExB2a4Rgh2wTO0W0/sMkZevA0M9YQHjXZlZ0JCnOFxAcyZmy1+AWnZFYQ7LUnEvg8O0sOQ2yNNaRpOEKveAlYkouCCT4EhPFI+8dIKdtA5VjvAmI9LG8bOIo4uP7b+hBI0U7tWoL8c/5nd9iRCpbLkng4s3D9VaAJHbotU2cBueocWZ5h2Pm/IG4rULc75w3DnWs0n8EnExZRBeLhsY8532PktuWQRRoyEbkt2IhEac5rCGfDt2n8KOdBy55HrXXB4xnOB2ZlEMI74MXLAPe3h3IJQ2ZqPzf8CibCftJMIh1ykPCIepupefFoFX+wTEVyEr6qeKqzDCAsNAyZ3EnHy3L1uqjeJuN3UvxABvygKsyZCzU3ePmVQirg7NwXT6ncxL8NH/h/M2X3QXyI3Ep7w1b7Uykx4cC6suwCKvvJbfAE3XKDZKOlHInyVsvgUYCSLjtJhmHJlrM4HBhnI+j6Fxx0Fk8vgeMjOwnf/zP1bLUlB3E+dH1KAB//r2qABgwQ6yS7wMYPtYiI8v0LPdhtaLT6TzYYMYgwzwVQSsSuxjTUWWtLnSqXAH0IKjyug9jzziTn4pYTP4w98Hi53jSEA/cjv5CJnDPa74xCfEHz4WuSoJFRY4Bw1hYbffoQFwEz2HY8jYZGhansiXP+rZcyfRCLUbywHisMe9ccFsnB3/pKsIbxtGX7sJsxM1837An2Cznf0w9++sXSTUDn45f4FeFSjnKnsJvLo2QfFd1BVof38R/hRfLqMPRX9xEF2jwkM2J5iYQO1v2yMdoYmu4dOqaajPkdcIo/B969/lxpCFo6r7KnQhnnxeSvs4+sc74X9R6u5vsEDPkXLnBkkgvnhnIQQpPxUsJGEsXfMEl1gLpeIYA4MvFlq8gzKSptEvoa6U29ITpnoR0HxT7ygnpTzKAXGvfllUw3jr69c25yFuvsg+YEdDm51+iMAOY9QRynwQOI8Tzj0WfUwiofZiYr21ZD64tyPJZhLCItsvI+4j05YbYbyVou5ldkk4hjd76EGGFlHw9sOOY/O5fPlkAjzl8rRllCaKb36HAzy3bDmDou/aal8gT4JM5f64eipjCcT8Mig/SfeXBKx2DA6ewKafezYawlzp5sdzsEKUb5qxnwSIbNz599t8IwQuyLvv7Gwm90JGPjeNjIYFrLrDTyHzhsf8bz99/fNbGb1ULt69bjoI9yvi4fCZKC/ln+lEjybKz5zASYZlEnkQ97tx5yew/sLnVkVUG7Je6AONu3cztcGfU+9tOiD5k76Udse/+vrBmWaUMpGYdkAsrKJylnAN6vUwOoy9DPjgeom2NV8fNNXSFUQ5974CnE4dXGfBAwXYvOSg3XsZc/VoHvTp5DTMNf0Wq0T9KA1YfGGW29FODyA2+Jb33yFzD3dtMOwQX/y+DRML4+xEatGnxdYyN4PufLPzirD283jdh4wwrQ34ia8GRD1ORMKf1bmeQS/ypVqizfge0BkOkUWrmuIjanADzn0r8kw+u62o49hfc/1pBJ4VmvXUBU0umMqd+gribiXbBOtAfXKLwzowfEz3w5dhuTANxqPYHXe5tSX8DaT7Uwl3Pfc/s3lbhIhtmC98wr8z9naPQaSfbsD6qCbEXGQrgf92Tc+jhVebhkb44QnUvc/CBzGun3XN0bDithWm2TIZGwqXQtjflE2/IHTQcmnGUbQNzWKyrbCMpWvHDxQ2pP2kgj8XHfomAWkSImkXIUv2pMXbsBDJf8Z3YOlz3bYHp4jEacNK97pwkFpL4lTMOnI2lwGrFJJIr7Bsu7Mh3NwqKyEeQ2qdbV5M87/68/LX7fBvE4BdV54oPy42kn4aZQ7MBRmaUeOxsG56VXdVHiU5f1K8jK+a2ju29+BFopRjbkwUT+ZbQ2yek7rKP/CPRQnU3wUys+Q+E7CmcS6cEvoQxL4eQ7WZlIsPODETvGWR5CFlODXAW8Fyw4NwoPNnbpT8EXYc72UFdy3I/Yv70H5cM7dBVCxYE1hAF56GG7Ator4ygWV8sM9jEHCeyBlpfyTETxH22HtD9uUt9SGw5QS/QMJ8GHm3qD5PyRiR8jRqTUYkeNgvmkN86ou6Ruu/aurxV/XIPOGCw5p8MSB75/vw4l8D7UncPD8Sl4prOE4d3oYbteztWb+i/hRdtfthEMz3+UF4flb6gHGNGTi5Zvr06fhA/E5a2d4Mezu74fw3fnC7m74SsZCdwxeV2d89ROWv22YEKYlE48S+H9fgBv3LqQWQLMkrv9ewrkjR8mV8FeFxnrCf2TixlKczy3Y7Dc4/hAyvDLJHIX0ihIifJvJBNvx2lQxuJ7pxioLG7U5QlTgFZXaZS3YJuZdHAZztFgPVsJv7NvyG6DZfu5d7fD3zT3XB2DUlpc8FixYf+STBHtobPCY0R1KnCmi+sHbGnsbC6DeYArPIOTXHEr4DkUWZDctQZmLbO/fbMdzR/XV6mCa49WXrTD/uejOTTvIRPi4t7MhFMhU0YiHh5yvR/+AxtJdjpJsGE/PDChA29XNVhpwWZhNaBsnmSigDb7DA8PllnhE4QtJBtaTsKTe3fXyP/t5vgVB1mPN52LgoSeBtew8ZGLwSqXWLiiSw/ReAj50UX91Hm6j7TUogXPl1KYq+KpRWK8Jno7iKfzGi/U3+cjMQ3PHlidrcH0irkCFj0xskfktSIZDbHn3QqGfwRnBa1CmrUTk2G4yIbpmkGMID1C/S1jDAE6Lknh4Lt2grhmGLnGa0wlhng7RHarwwnGpLC+Y/X5N+z68xnK2+yt0ySg6rCNMJqx4dXgCYdHbg3eioEL5HqFk+Gdy/9UMMTLRsrBhey40M29PKYL9MXby32CTdPUOMXHss24kdT/Ues28SwU2ssQni+0lEyevXOGVhUonSfdV4OG8pjYK9PrbT30KSziEGV7B3Kvuce/hoODzxI2SZEK27B0PM/z0uOv+TljA611HQNF5dr9LsDfEdWMQ5PKqiY6Gxqzn16xk8V7J4ihHeCmffqcXrC380/oAhu/fxPAJPprme093gEyU9Z3eawF1zyVPxcIS3Zukm/BuYiZDFhzoUbPgViYTjCYtk8LwlJSbvzRcONxkcg4OnIwYLoFf3ujlTsPlX7bKv2DODVITjQqZsDzA8FVGl0xoHDPxUYZ7P+SwakHup7R5J6FI++zrMtitGd29TY9MbBW29eWFRe5KO8RgrTDvk/1Qa/ysbZsRmfA/dGK9D174dfjOBAyNI9nuMSYTxSKqptZwhYO66AjVSdXXvWC49taD/vBup7fiayicNHqbx4RMOJxKVROFNFHG/TLweoGj6iFznNdQyoAGPBvdHKIP22782OoHM1hcs59DWuFhnbdwPf/Mj3q4VrZ/rc+STIit/7o3AZeef9BagHeddgnLWZGJqUhpjcuQYeeukLfQqSb2M5M14r91qy8blG66ySsAn6m/FYs6TSbc6yU+JkHhuvSLGXCLlxPNBBzYXXWDsCET3+3TVHXhcS7SiClM4t0jO3kWdfi2rXsBinSFh61D4xhuCR17MsG0/b/pJGgfEvywAtLpxF1agY3rgwL058jE830q9VtgzadbF7mhtdiw1ElnMnHmaUe3Jcx91hLpAB90ck+mwVtt/Bz9MDnC6d0E3Fb8wmsBDu3+RPPFBb8raxf2w7cfa20nYekIIze7K5mIf/ahSQuWbInwN4TXx/X3WsPjJxOuJ8Aa9ricKVj+4InZMnzxtIOBxo1M/He6h/ToAupSklWiBMaStLqqoP6FXX9o3MkEqckx6iBsnJhSPAw1g0mTuvCty/fhdni2uSV5EF5++vboFCzdVsrE4UEm2rttPh6G3/giAvXgvZ7nMmZwYHVuiMuHTOyx87whDP9oLGhLw1WeiYZzsLH8BM0D+LVdKLwLMgvvVBqFEj9Zf8zAd8pmG4fIZOLOXGzpFOzc2+C1DL+IbzTeTSETnmz3A92gKudZoWooGCbY0wQ/XxxP/gpTW5rE9weQiTFaxmFlKFuqdVsLrjXpr4bD2bNrd17D99oxljWwr1iAvQWyr5PWpoPx3qWksl/wpU+xL20ImTiR6+smBWuNXitfgKSXWUe64FjauT6mUDLB8U7qFhvcc3HdQgCqkgb1aGLIxG65b6ws0Iy0+IkDOnl/PG0Ojz0qrc2FHGG7Y4ph5HiCfgUsntPwTEskE74qIwcfwGNsV9eewE8Z8v2jMN741hJXEpnQOXa1XBhm5j13coAmDdv6smHcyqkHz6BFSaZbOXxFt3igFraYn2qLvonnC5IzrkP3hE7nu/BrZLJ1OxRhvhG+MZVMjKTzGjLDr69zeThgAl+o8/Z01E+CnhwfrL3Bs0EcOpxLlTaG7NZtvZFQnWs0NwkOOP+5lAFt6X623M7DeUnK5ORAudnL1CJ4vUY5ZwJ+izuUK5GPc9vx6YsdNNweke8KG/I1r1yGVElKVfEzMlGVm3urAi5W912uh27mi/2LsCNJVnhfEZnw7sr9exAerBDrPAwfJsu/ci9Bn+AYukmCEkrXL4fCRtb700+gYvPJC6tQxjVy1qiUTLDsftt8GgqQ/z5yhu+3VootlJOJo+MNm9ah1pneCaY3ZEIlfdv2U1Chc4fYQ2gyGbmpEGrfoZt8BX2HHbpUq8lEemzOm+Owv3c20xieGn+a9xyqhdr9XYPRNVGX5d6hzu0drNRh+8NjhA70PsZb/7IW99qp0sIq2MtyOrUJpkTNC9DVoe//ULp2FNYnSPmehBf7xG2tYP7tm4O/65GHb27U0zWQCZ7o9KItkN9q1kwZXnoSvuYInS/VjHnBq6Osn/yhk/6c0Z8uxFm19ChjN/KvP/zQdphhtYFODQ6s07wI7P6X71cWaqBK3dvxFsgwx9DdC0cEj1afHCYTo5Rdr6zgWgxNkSPcNjFFLoLe24Qqf0AOLvvS31C0I7eQbgT92LhHfHkS+zNxEaH5TiZCtq4LssCPGtfZFGGaj8S8L9xy+s5AKZSMNRv+BtXjSAPz8KV2Zu9fOEfHbbH4A/f4NJf5hhnkT+Ius81wT9NDIw2o5vnmhPvMv/626QQJholaGIRCg2c5zq1zyAsaRpc+OLzFzXUCfig84sU+j/ipx/sehiEr+0l68K9PF9kMbqupuBIClZejQuLgzVHLsNR/z7EMXX0P7aZUrs/C8BidlD+QY8ImlXEBdSi97Kaxin58OchHHx4M2ko2h+FbtNKvwe3/RZV/gJ2u9u8+w8Vrmg090E88KfgrDYW4KFEdOwyN537f/AE3N3F+4KalELffUxa0oEPIzLohPMbosvk0nIliVuPcQSE+iskbC8EXSeecpaDMScdyS8jSKb//KjQIzdRKgZ/X2K0z4e/yIj4rTgrxxZrtoCM83Ugx8ILrkb6DRZDP/6XaGPR97mk2Cz9UyHj+game/usr3FjPT38uBh4KkakRemAbVK4YTVeFjxU76VxgxQ8+gUvwv8vnFYPg/RONqS/4KMTLHPLzSij5RfpzI/y1c5c1HT+FeC7GQncMXlRj22UE+8V3q5yGdMXj6wNCFEJF3E5gCv707ldbhtHkqh4pYazfvd/KCt7hyaI4QqE7F9K94O2vYjVCEhTiYRtpUgqa5rWwKMFHFrL7j8LnQzdNTsKLRxn8rOD0FXK6IxS/ufjGC+6J9B3yh0tRKpaR8LpkIzUJMuefvZcBbWk2vM+Fb4dKjdthCYXkOwif/lBPn4IFyiwVy1CbK0bUaS+F0NG43VwMT42PzlfAT47ynA3w7dsYlXa4Z/Gb3SDcQacfNgVDQkhpvyD12Pc3tPsoxKYx+2FWKGE7zMgN6+fY+ldlKcR3rQ5GxgMUQox0V2Y7JGsP+rpCpefBn6rhLO9el1E48Yia9BP68HW8XoV0yUvaLMpY58BTX04YvMX7gRC03UkZ84IShXm9xXCEaNz8Fu4uWlBsgF/L+5s5jmAfW+NohCCb9hF5KcgavMPRC+aHadwshkVehg0VUEfT6W89zNg3GtChg/z7z/LFEJRr/TI9DUMv59CK6lKIa7cPcNtAM99Vw/MwXrk+6iL02CbX+RLaqh/YVg1nzBS1P8JPiRVnGPQoRETXFooatGM6W6QNeYVefTeBltc0Jr/pY1/56UIL0KFo1XodxuUf8VcwQH3xht/ygC+1ZNvJkOf06JZweHBCN+uNMd5PqA3UQa4IBb4vMGeYasBiQiEcaa4fUYLNt1qDjkIxUa43J+HMoTO9bFYUopLcxb8L/nlsabcXWjROT7jDzVbDP9PhidUnstlQIy7k4jOoe1X9Vy28sCym1AZNTDn8+yG3NncoszWFoDX9cVUR9qnwNmvClxyG207C3QUlHrvtKQRjgcQLSXghM+vPIXiVr2mnI4y6HOmXAVW3HKvIhYUZzAzPYU/7ZPwBV5xDsHmPGjy7p0lMBx6MGzX1hbcC4kLvw6eLhz89gWlOf3heQbH/Dty7foFCHC7i+nEXSpszKhdAo/69TD+hyrBFjLg74mKW/vUADKwdFlGHBQUZl1N8KITzlHJNJqTfO8DxGIqYBOSPwR2cAjM7LqK/6DERAvBW0Eq8BEwtmhuUhw+f83oe88M6/typNoJtmhIcNvCHd6pDDPTut+6ugrnyktIfoUMsXUgnbDp5/+DLaMRHJ+F6FVzQD1togk9uLMXyxVCINwFxLJ7wg8iUGwX2dJxsDIdeb1x+v0+kECdLjU9/hmtVRyp7oGF2KnVfEoVo7dNz9oCHyu40kuH7+79lwmFcxX6bHDgzll1VBK/ziYhVQL3snGDaZApxnPm/K9rQa/PwqAncz12tYwfzNjYlfEmjEPbfilcGIPNQlv0U/KPT0imTjnXGD5t4Qw8PsTdUaHPGWywKjkyMNL6AZirGB6ugeGbtnaZ/3ubj2n4L537FpJWABp/5VfUgk/zPh2bwUkHtVntY8HNVevz2v77bmDYHNXyy6P/C7R7HCvdmUIi5YNMYYyge6bZkA/kzo8+4wKdbFmWnMtHnR0fvLsPall5W2iwK8e6YRtYxmDc6150KkzkNdB7A2bNPS55Cvod1Pr/zMN/ekjG6fNRt4yOLrTDtIx2zKaz6odV8GxbM39TIhYJsc8+L4bTTcDRHEeJ+v5NGCPJv7CBLwTb/7jlFeKJ2veg6FND9Qf0DdTb4LDEW4/y+/HXfARXqE8b54fnk6zx+JRRCU3L4Rgg89k1h+zXoKtGy/hoGuWx0WYJO/rdHN5ZSiNKnxBkWWJ1Jf4K3GnV59ucnMRitPWR0ALqad7epQRZBxl43yP190OkhTDv7ZvcgVK/Z/WAKzhjHif2CjzZtzKN9h7rUP0HP1oA+1S95VQB63NqxYy90uc+s6gnVKpU4SqBbKTWjGj7urRFphkxSXI+6YGHhU/ofLbhvTnsm/IbRigp89K0UQuoofe7W1n/v9z2n828sKiDyAape/RLJ3kYhbnCfZBeEpp2f7+2DgRkksspX1Nt8FNNxqEW5d9MY8nx6P3/z3+/v2ST6YcxAVOkktJRi0F6CRk+VWee7cG8x/sn4C3clVUv/140+ac5OpwmfVQ4PfoKbWpmusvcgDpoBfILw78Tvx/ug4NEJy6ReCmEeqTudAfs2PA/Mg5Vy73/MwKTPhcxyfehHG0l31KG/4zFZXThIt79Gchj7aNx2WhEGNf6e04SMnD8GAqCR3rY/zbD5yg1OwREKsa9FKd0K/jzVsd8JhrFRar1hsfDh7i+TFOK1yfilQTjzNnnrNNylrFoo+51CRIoZVPpC4fsW1iFQ47TbchwcMwpPTIMcYdmSD+GX/ItpbfDonux5mikKQaIyXWOFfqw+EtzQP46hu2eOQpTVPCZ/gwaHbbgXIJ/TIUWpefQDnvBHgdClO0k/Bir05EzfgGEaG+Wsf1GI+WscHU4wcZc82Qe2OZTa34BJR2xdxuHqeRM54d/4Prg43SENM6piKcrwrIm8wDFIv1B2rGaFQjy4ZjHVAl97rMf3wZPJBfKT0O0E5YLwKvqJd5mgM9TvFHC5CTnplLbch5U+VsVP4AnxUItX8EICQ2PfGu5Bvavek3BGn4trCZrRvM0+9hf3tbrMdBRk5RRKvg4XDvIp34NfNO+8+EzjT/y1UbPrhXWVI0wTUJjpHJ00rT/xsvD1zGU49KEyNRjSiHw8EgcFGgenUyHx+k/KA3h+kV+jEA4U/5zsh40Hbyaz0vlj/j9q3FCUw2lCBEozmeSO/udPXG9cM5uFzT2PGdZgMP/ryr2b/QlnV92HhlBaRs30NGTSOER3HpL5VR7Yc/oTUx8srT2gWnXQDgrcEP/XphKSmH1CtnL5E676v5R4YfJQ6JwYfFYW8rOGz584YvUnrxUGG/k79MMQ5Z3vRfj9iTwmMVc7OLJ9XcQNcvv0DfhCdYUKKS4hf6KvPGZKGM7ets2TgWoHZ/l8YQiLc1shHNmVnFgOmeJqTtbBZROaLV/gi0uaTQNQ92dszBS8dHotlEcY62d8EqgDeQuU1E5B27ymP2fgdhMWQ8UD/sSeI/OcR6Fg8sDASWiT378hCFZc7j1ZBr+ls3F9gIeEjAc/w+fMqbm98FFyh5WwHOKR8cnTF5K/URVDYMB1WZprkKrzlf2Vkj/h0+A99AEqPWN70gJpj48NblTGPL40T47DNPO/2mHw3Z2dHAlQQv/gyC0YvnGdsxG6Pz4y1gFfVF4rGoa3b82HSKj4E5wzY688oJdCUhQFBo1pmUVA74KBqN4jeM97eesJGHA8UWoR7uL6pCOj6U9k0m1wdoVH+B8r+cKGTHuWEOguse6+57g/EevAoCkPo1jYuQ7D2z9SL3hCk4NSN/Oh3q6ICy+hg++4RjWcjOQpCdf3J0zLguITobvVtHMGFFKdrG+CL0NcW/9Clh08Bf8Z+BMnt7eE7oReLpYhpWex3rEt599Dnd5Gg88wjbUuRdjenzD2FTdzge7iBqqX4SsTilAwFHJtyiyHeyliUXUwiSHK4wvcujows/Uc4tSUb2YOJZky/SLhiD7FNhk6sVpr3YXV9utvOFxxbnW/coUg9dHvZGkYtpTx7iFsG2F+8hvSvU1Oo3dD/nALh2+D8YtlXnzwN+Pp03ug5BCNtjzcr/JU7jBk9nTcpQ/f1e1mtoC2WWPL5+BoMvOIJ7Ry72/2hzU1pa8iofS99OxkyNi1LN7q7U947Gjm7If7Pj3a9B0e3Zr8awlWtF75RuPjT2Rx+35lhQsjPrXcsEzWr0QUrtKG5sjC1+YpN9UgI4+LgC48bXviXh6kRmk/moUNZ87HMV30J8bu0XkKwpnDj+0k4ZqDraEi5GTl1DgK22kZmD6ScT6nh9c6Yapa7dwoNM0uHp+FeSk5PWvwzpb7n5koyOst2R/YYdCNwleCkPyg+qkklFLpfaAI7yabTWjBr0pBfUawx/lpqw20jmiLfAZT83ln6fz9iYjP5WNbYU6gYw8v3MC6MVPE/1/fKknZDz13+MWq/hsPqYVoQ4+fsaxfgtHnaimbBmHeXi+aaciw0twnF+JPnPVROVsKj1tIbN8Yiv7R38bMAiXmwhm54F6iVL0j2p+4NvRMbRiusRWrzkBqx2uVVWikGK9wJAb96VVuczncu2L7cRp2JTF+/A1F3rxoor/qTxSpfu/pS/QneoPmByahiTnt6BJ8Eb/xr1qSP7GpgI0zAt4yyJKqhjkpygeaIflSt0I3nH39UGdzsj9RnHbCRhkmFB+wPwa97QWcjeG4h2jEsXTU76x/vDHk2dydaguPXxGqS4fqHcMzDVB2MvZ3B5S+oU47AsU6jTo+ZvoTLdtcRrsgMR45PwbzNa4rCWUhnnrlZ0xgp4a4px3UbU8LcINnv5z9EZHvTyhu/LMxGV76eIv9LnRg+3pnAWr8uLZfuQD7S0g/egzOtT+2MIby8Uafbxb5EzG/6Cfvw+sMlTSFcHi+OuU3fHJkQvRIMfLsDSNxAsb1SVpY/Rs/sPJ2gq+2JcT4QJNp1v+eQrWSlieTMFfbum4JUq5MD9E8xzxWd51+lWG/02uhdK/8iU/i9plb4ZzFX0+Hf2PzF5sK4VRvuGg53Mxiq1kHi7cHUzZV45yLl2+zQTn6S293QVvalaF9sE2t9NklSHve2q8cDqkdTa+D26rl33yBZ7M0dRjeYT1LX9oPwre3Nq9oQJfZ43wnYM5CLGEFQx522TvBRMJyNgX6XH0SWAsXzx7OaoMm37o+DEDZb5tpOBvQ9y7f2iMM77yQM5SBr13ucVyAN9Pu9udChbBYxhfwzO5g6Sp4fDqmdrDLnzDn4FuZhpx/nu9dgZsdRIUVurG/yCq+i3Dl4tMTQXCR5+GVq/CgzQupn0Po1zL2Dn/g3SqOW5uG/Qn6IAVfRRij3GXkAn3C2qIuwyNzJm0VUKfrhBn7iD8hM3Xe1wi6uy0/toEuBVfHXKBkwR5+X8g2dOfahW/+xAGJ2joS1JT7RRsOrxQJ3uqG+tdUy3ZPoC8pdC1IwXf3AqSV4bqKSdnnaX/ic/XEci8M2BIhPwmb/3RmH/iBeesP3bwE1TmU26/A4D1H2eLgPL37qMi8P1Gg6yIqC3dZuDupwYOGywUU+EZuTbobSitNlwgvIH/CyypMYcNVr41n4SUrmSPu8HHkloarv1Cnn3y2pMINQ/3GD+Akj1feEKQ9Te7Y9RvfOSIqvJKwooT+jCI8fn9d4T0Nlaj8MBj8GZqXNjT1wne7mLsP0FKJVmkX7avwgFld8k3IdUJm4D5c4Pfl/PgflVhx8XHugl4xviVj0CYoZNM85HzkMaGymUp4avZd6YTSHh6rysxU4lb+Kb3jUL386G0TuH/kWvQgK5XYuFO0dxpe4n8nvQIVs6LJe7dQCWs74akz8P3iJnV3uPPsYgIZ9vGXRXdupxJPnVr7R6F21ILcHEzktZNT2YH/K3VPuQTrlmnSRuBCqwy7EhuVqH0u6aoFhbxkK41gQFbV92lurDOdVmsFRnnq3WXgoRIi8VLnNKGtNzfHZXh2qtArGH45YtgYB9/4/RJNh5ZDkcdG/z1/r3CXNC+VuMBRQVGGUa5t7cfg7b//Gd4RohLlXF+e5sOXO7O3lsDMXtX4CUhHv9VLTJhKTH6R+XwALkRa7CegxMSe4KADVCKsf/vUVWj6lvZUKkxy2/m3Hgq1SG5jkqMSAz0XKOzQuuX5qCD8li744LcSxp8/7mBQphInF0OCt0MW2/M8p6GIwJN3sdAm9NWBNOj0tTnzIbzuwJ4do0ol1gWcOG5C/fq3EffhYOH29FVo/nqs5rgalWCIfHLIFK4fCco9A3V/mnO7wwNPfuwb10B8ePPuzkNN6gW2DUcwb2GWuhnc9VEu8x70ZemxmoJ1S3UdBzQxP5O1Hh4morcsvdWDfrOMoTrHqUTNsYOrp2Bbkpu3PRQLt1B7/O/31U17V2HPu4eZjNp4f6geNxu8zL84GWyMdS3pnb8GbRsKxtNhuUdS3xiM2L3ZXMSESrDW1Lfvh++dEk3VoEySn425OZXoPTnefw7Sstic8YJ9PyKdsiDDa4+fg9DG5aD3D0jioF9YgecHQpbczlGJOIOCQBKsquzZFA7vGBx7+Q7+ZbrqQueA8Qu2ha3wnvMDKh/8MHWzr55CJWRvvrjcAb1Me1hHoLdQ+nlTf7xXvaf6PYwwSbdugXT+Zxf74LK0uNFHKuLXGP+9C45RNoaNw6Bltu9cAXjf1do4fag+fkXcEgaaHqlyhPaJKR8nQ1Af4pOuy9C3TZOJLpRKzN/IfrgV1q3eM7OGJhbM74vh9KmBs5VQ2fX1ho9QZr7HwikScRvesuID877rpAXBL331f77CcrpLP6WjqER2yJ4EFVjOM7ZfGyroiHxfj8H6r2XHMl+lEpE/9stwQV4b7g0OcK/NzNlCeJ5nmP4NfDvfl1MPA1RlXWti8X+mX1nboGJk+LMBqPxrn6RiHJW41pGwJRGeelRalAFV7kyY5cOZ+phEviQqYSWZoSgBHR6XDByEMgmmPtegHltGQBdME6fnY0lGfnwpfMcFj95zdBOFJleF2A7AYk/nIgdYzyHJcwte4T1QnQMfEIddn0NjXeMC35voZ/Ktp0LhTcJqYwIUUlvOn4DabgxDoqlUwlDq19UDUGv7nAIBZTkXhvTgcRrj58fSqUT/tcwzJjCBWGE5A/2rJdzuwuTjPGtTMPVuW+5vuI33ximGW1Ti4mfTpUu3UWdXNt8PhqqmdYbX4GHt8XPdsLOPqieSQSW6fo9rOsIJ20Pz3rB2Mv5eIKwuIls1Z6IvG95l7oF57B/Lv8GiyZhRuSwq8axlldEL6nrGlFKhv7yQazTU313NmwKjWWg+cOfg94J4shhMuSQmLQf3ZFm5BkGdhp8vKyE5fsLtI5QOmhTshhPGb9xJj6iEi2WFaDhkiqvtS4Sd8l6+LdDRKaiO/zHqqOz7lb1QWtlW6RB8JUlX2/GMSvB0+4WMwNiSRbVZeH+LsqRwEc7FtLnDHh5iz0jyhH9zd6s/hROW7EMjMHNdPmMW0nyxsfwLC7kkGwRKqETDMYbofXAoZ/y4ImS7WkdLgu9VrRqrYSvdnZhPUGl9UqcX/q4e57haTiU0tNW7bsIIuju3HsAVFs+HX6G5wurTzW/w/s77PpxQ/9mpgyJQfnpa40sVleh2KNg0BJ04fD7+gBIcA6OC1ejDEpSeZNhVEq/fD5WGVndMQfajHl2/oM/g5F36d8jnl+5O2+GAJvW4EYyzvSV6D26eDJ5+BN0eexWXwU9cdK8FWqlEcAVxdR/kzw6zVoSHO7/fdoM60lPmBfBafsieUrjZRWjlPaxxaahv+ecjSno/5CnUCdrXhnvtTllDOOQK67uVBCMf/ed+F26W+OXU0U0lpNRaVUcga+qLHbOQHFXCodaDuKfnDkTDZ/G/XqTA4cYTsffh36zZTYbDVILKcWf4NBz4YvLGBfLNnabLh1VSirrfoV7hgaS9I/h/QXf3Q/By71Pto3CoIKcw/Tvi2PckIQe62lZ4PYedsVEti/Ckd6HJninU7RY2+YNw61oA+xGYaJ8QMUoTQHgUZl2egxVWbxzWYdTZQRNm2gCi7T2zJhfMCSMOiELmTP/dB+AmnsptBLz3k2WjPhzoERy3hI2uge1OUPfn3P4J2NzFEH2ZLoAodOIlh8BxQyWXeHhJ4KzlbejwLl4nD5Z/qFF6CUNFGfe+g5U1CTyfof/Q4OY++NpS6c8kjJRJn1qGs4ckq2r/CyCi91u8+AL/RMfmDUGDo/UZMzDcbkvSH/i4xzqCaXMAUV/6jLITjixv9RSCNCm+52Tg3kenu1ShI+uXjzrw9SeTajP4UUfAqBPyjVP9COYAYj2b2d4SLjmpmDvB7KiL+hchB8tzjSuQ79yf5ZntAUTnU/fZP3Dl7MQk0w6sl+w2shNGLy/3CsFNXTEdMv/cLf5ZFT76RH5nBp81z/T5wIIdL74GQePy0JZY+LjRqjEN1hxW/pANnS3FMxf/Ped37LwGWwDxnTvZ/gTUFZo4bQ2/JGiZn4cRXB6Rl3kCCKUAh4gQyKZ/LjweticdC/oOHfa+iFPmDSAuNEjEHYfM7dmxpnBgmC7pqlAAYXrrYEoq9K32TH8In87Nl24UDiCSrx4b14Oi75a/W8BWl6c/HeHdIK9FH6jq61jitjeAkA0vriRBtU2bG8JhkLQpyxDcYbFhec++AMJ+T9MGBahwIfM/TZgiHMRmCHcNGX4MOhBAcLcO9MTCF8p+39MgceXFkQn4xmC6VFUugNjXNFerAzOrN3w1g6J1bO7RygFE3+X2Kynwxd271+//G5ds/z0Kw8TzT4upBBD5uS1eclA7myb8MByIdGYKPYI8kzfbnQCLzhooZ0B5/qA7LXDbROB5Zc0Agumy8IQ/ZC8qpomG2l76vCmQ9GfwzYRuALE7VrN3CQpkPVml1Qsg/g5qJR+FoQo0W8jQJrRKMgJ2n4rRS4Y/r99RddQPIJr0flv7wNYoK/8g6HrzA1cV3Hc9/OYSdNumVkJrgP2x/e3YCkMeFBe8MgogZnzDmmthWKvN3Bc4m813j8M4gBB2mfJxhEu1rcI5sFZT7fhzeFyn0LUKqvPExHNbBRBnKhtLxKD94s5BOdh88nrweTjIq6yfD7V7uy6VwNG9IRnv4atNcjUtsNVneqYfig8xvxa0DiCOCPgvnYNcuUkC3jCqsuh4IJx5OFczbh9AsJRMLS7AjdYzQjTnsJ+91P80oWnz7qIE+MDs6mAGlPL5u6UAbs3krR+ARyNvKbI5IF9arJwF4bknQilSUDdbPPOrdwDh1drbOQr709K3zUMOhmo7DR+s273sXRjsb+zqrYG3v0ns/AL33g0xGIJ05UE6ny4ijv9RQ3qh88KV15Ow9SlP175LAQSlsyHYEz6gSr+mwtg36YvRcI9qQ6KkH9ZDXW5Sgset9jEdh6Zx/BdS4KnzOsdHIaPJTMgcdO29VbEOH9PfGT1ECSBW52p2a0G9oN+2xlDuvnfidRgdlBiwDqsCXB8e8cf65oiRk7CfXmC3DZR88opyhRpA/KdoVxYH5c+x4LMH897/7PUdTp9l26ceEEC8q9zvqgeNq8zyLKCszBcnmpAAok6MJW8LbKjWn+KFspPhZDc4q9Pa/hzavCM70Yfi/eRv/Frwc+SvM8awXGXbAzuo1Cexa0sSztu9340X3s6/VboHHrasCidBO1WDu+Uw+o7PdD289+Se0lfI2vKrdjktgPha/oWbPj2AyLV65bYd+ogt5XnA1Ihjql1Q6prXPolb6KcM1Yd14N2twclm8FwTPtzggcvPmWmyAojEqx32W2CsBc0rXijZK79dAk4LlX1wgxvUFIbHYGZ2voDEfcxfEeqrAItiHZs1YcYOQzEjKPRDi8slP4BIuNNzyRdaMlNaQqFEc07JDPzyPi1CoiCA+HCxaEQBhve3HT4KuRnWM4zgsw80141fBRCTbPR/7GCS2FZ7d/hgU4NjIbQT/Br9HU4/PDL3C+rMvrRgeI1xn0WrQXUAITObpm4NSY0j+eehfm9nXQEscQw9yPAugLjzVCFrB/xRPb9FEFpsVnd2a8BzbvWdJDiaZqMbASMTakLqoYkavTRPI87nNj+jBeTMUyc5Qqmw8999YFJCikjjd5zniVMFnXDHD74D49COKdz60BT6pOmjWR942a/f7wqsoXBvuAaf2NpE3IKHs4plu+dR16+r3nyDmWWdOkvwEncLo9IC6qB0+T0VnonzNIqBucfn+m7COxd/zEauBhDSjowhN+AKsYftPuSuY7LogmdO12Zs/RNA3HdTkuGHng7PK/dCDqmRpb20gYRazMZYRUjXLiZ0DJ5TvLA9Br6q50vtga/bbkfvogsker5bCUpB8dndJcowI+wdy/7NgcSAo1iuGjyjlKSpBx/FyRnEQ87OEpUPsFo44GsrpLHXuzgIX1zaYGLAHEikqgj8tIJ2S1pXz0OLDLOWWhh6IJXMyxJIrB1S45CAn/ZPFSnAC1mu8+ZsgYTcf63JjjDE+cjBi3Bym+G9VijzIPebKHsgwRqfEi0Hv3vH7dOAbzR7ZBx5A4mfjNc6fKB+jU7AFfhu4YJTK9TRuv6MjS+Q2Nn12mI3vOQyvUEGCvxfcX3HU9mGcQCP7FF2hLKzIlKkcFNJUYqsjOwkMkso5xwrKsloGVlRZnaoVJSkFJURGmbJJhTh/b1/fT+Pc1zP/dzXuJ+jMvn+mwKF7M5ro47BKNkXKovQ36xzVkWRQtq8RR+7waQNtp5n4fvW7A3hUHwbHxf/UQqxLqJ0S0CWPb9ztsADPfXpZ2CM2IXkGrh3yuxEI/xZsd6J04xC5FvZHEzgw+/7NttDH86rfz0h7wfGJ+L+FCJZn5GqDI/264dowRLVWTtDeCK6JrwAqowI/ZqClzN13qxAWvTpAs4zFCKUnhMjDAe8+1gzz1FICn/g2AMoMCrY+gT+Y67bvTqQQj4c8/moCbOlPB8awOtivsnmMEXfI9cyGPGb3l11haI0TX9/yLru20Q11D7+Y8MStBd6wMB+nkK2MlN/CcITRpH8B8MpRNX2/SpreClHfNQN7uxysmmCFacUjjNEUIjyzdkDPDBvsXG7GJzU0FPXv4x6alHZdBReuCu/zhFuP+recRvev/8p6htU+CIXOAbLDkWdXITrSyeFI+LhUCFXAmSw9mfMgO5Vvzo74birkwx3AoUESV8Q3gh1pdO5NkPeFf7qDVmIx9ZepQh/HU+r0oQsg1JVKVBpM3Vg010Kydo5eMwBtqwOtvaCDuvW21yA5U63f9zPp5Ahb4axSvi8+dz0C/g4Yo5XqIBCviytlvOGZienlELgiNRPtSvwQO1N0V1lqINxFtkD0NY3TNUSbveT8S2AKmbqIgblyHvCe+4UWLNaXjQPar2Oka2Cz5hFog49opDUb8M3baAl1/N77rCBeo35KUzpHHyw9jGFxMdufyYKu9KutShArT2+ZkfqKSRX/Ib7cVhkU0/xhJtP31x5DvNnJj8zvUD+Eq9O8MGeekf9g7ByaxVankLeSuaVJ0AV3+ymDBhOv7u/tB99YjPH+Rw+kSnTeA9/yQztkBqgkL+Hr1e6ww7X+t5z8NvYAsdFqK8stN90hkLevVUPcYBHB46XeUFn50vL7L8pZP7Pl1YvWCZVwxwChd6kaV2ByqNX/ZJgdz/batNFCkEPaDnAwLClAC9oVH7U8T7Mmzc72AuZL8hFTcAAGlP9EtQY1VJ9uUQh6c5HT3+EO23983qhgZ5p8vplChGLLnp3FC4xSLE7QQe6rH0+sO2ycOkzOir548b14RX8ycw2/Q6q64VOM9NTyeHKyPQd0Nj/7TMCnX8L9O6DccpUt1uMVFIhznQ5DU50XCvMgXtMxFoK4a2afYNDsKTPJ1uRiUrExq0bt8KVJwdGNKF0q5heLiuVXNp3/EQx9AnPvPIQ+g8txw3DrmmKvgIblfy15/NQhT+uF8btgLlxhg8J/MqQYFnMSSWrWmjUh5Dd+cz9Wrjx1N1nkzD/k3Cn8Boq2XTCZJUkfFMXIysPP1eyVj7kphKdLXnfa+GMvzF7A0x5msA+BYVbPpcI81CJ5cknPRJQ4l02szzccvTH7lf8VDKepePzDro9T7nTBleI7tFpWHBTjW2tAJVcqy8S1oRPnbavsoMeN2c2u8AttyusPaBgwjQz+3oqqWuS1uCB5R9s3YTgbuVaKy3otve2oQOM02U67wbV15wr8IKLLl6nr8AkrhduxZBhtevth1CwgaOpFv5SviPiLU4latkvjwRAlYmpyBCYI0+vUgV7xDjJKgkqMYps0xeFmlPe56Wgvgp3qQLcdbfHVFSKSkSOvr8kBQ92NTxXgFwqKkEuUIzue+I1uFpQ7C1+a5HzjC6r0+DovdqiVTJUwpQ4O8QM4yxUNq6FYS2HVynC4QEn7gNw2643+4/I/J8f9VBL+Gn6CvtbWHvGcM9HmNiy5kIXDB8ZY+PcRCWsFCV3bXg/VDNrLzxnZ9hjBOcyngdS5ahE3P1I+UXYwT40fhWKXKTI3YD+D14dqoEPeDf/GoVJwUH/Nssjj8YtkiZwrG7Uzgo+51qTZP//3/lbopUVcf9+xYbtUDHmKr02XFPxdIsjfBoccPsSDPPgbY+D9zXKeW5D52m77b6bqSTB4oZfICy49aGYCqOfG/TfhRps1uYfYV5ya0IX1GY92NoLRzuYC3xVqMSacWwkEK7n7lCgQdXr1fkFUPCc42gL/DMZqdgJ7Q2KPb5Bz+aHl6k7UOcHmFovwg+5VgKxcOhyeWUNFFZU5/kGt2x9aTEE74lapo5Bcy1HT1NNXJ/XLjsGM9I2/nWA9DnvzCOht9/y6Sw4G8xVkQdN3TYtlkD20fc9OVrol/yfUkXwyBEmzwqo9L0w5gPcb8Y2PwetflvqLMM9gQUXGbWRJ+kLUjG6VGLiuc0rEW5Jna5OhkqegoNVMNP3nPUXmF7mmjMAWRMtRFn1qORFn/r1zXBxg813NXhrd4TCLtgXxmCZeQR1XBlXmAvluiVXl8CQxwYP2mCW/3GmGRjDLmmzAF0TR0roTKjke8VrhwAr1JNm2uMQmFMRuC4SXtjNH5YFGdIdDjRCriee2e/hm5aQVR1wVjoto8AFz8FRxlAOf0y+OfEIbjrt8LsTzhfuurIMo0MuTjC6Is8HO0w4YcMZ1dsDJ6nEbmjjygj0s+BxmYGirPKvN7pTSWVjeqQhrND9NGoCvR9xmB6DmQ2z8RM+iOdydHkOtrFWnVyGfWYB4/K+mGOxriyHIe9ZJn8LKOyY/80OZm/q780+QyXTLC+NC+HPqfwn5fBhX+CZDzCarXLzJNTd0ZQ8D9959bOuwLG51I57gVRim7Hd4AH8ZfapqhLeirkQ/AnanN+26h9cfZPRZ3UQ6vBRVy8bLLEpucIQirxrzNBzQGFJzUBeqHvnZ6MGfEXh13GCNRK3K9yhRJu4oi+03cMa7xyNOK4HOT2gWeqNKD9YtWv8TBxU8K0mJVDWesvjKihgWaD+DA6OM1c23sY6lDx3tcC/lzrqOmDuMWNvjiTM1Ya6gypw9L7XJw0YnituTaB6Y2fvPti1OHjrfSru080i0QF/dm/J/wrbw6/0sd9BnR3n+6sBmZkooQRmvx1nN4CMvoXXOzMQb1+s+Hf4Seds4Q+oLaV/kjOTSnbcfseoCWvUZuJ04f4ZkQ37oZQQ7cS6HOy7zr65DdD2Mk+EDKzXsDQ2gk/76O0C4b4p9jEqPC+9/nwUzP+9Vj4vF/c5svdRCcxqpxhVw9qzqXEdsJLNr34aqs52H12AYcwHhujyqGRn9ZMnm+A2pXlNSyhv3U87C43GsnhDYMK9k9kRsFPha7l4EZUEPtqwXw5GnnH+sgUSpgdKxpBf4CTVE5Yd+sJ3Bg6XmOeeh+rXJrVWl1LJRe/2T2ww78LzUzzwgH2OnQY8urT2kTkseqNkYgc5X5kMu8CyjyVXUiqx7tIambvwxPPGZ/nwertNfSs85hjZMA9zQ5rtV2BPk9Ai00O8Z2iOpB+uphJui7e7LKFidmnncRj4hmIQAgOyGo/ehULf+ybz4f5D9DFlUH6wSnzuEfra1+3pEmxRFbVlfEwlp1WlPknCme3xhnpwbf2Z4f3QOtTu4hGYVNzfl1WLuX/mRGg+3O41KV4GK50N0lthftX6p/Nw5HmH3QpkXZW0zPQUfTIVaXO/+f91HmIqhlcW1hc/hG3v3Oi+QtFsHt9/8EUFrwjDO+STYX0DO3wWJ+3NC8lbb5aYVioxMOorT4R1HFYOKVDSTkHoAwwyDLNZ9YFKbtvuyNsAD+SusZCBDduGVytBtuI7n+LaEDe+Jew2VKli3poBswWfH3oPdS/2tCzBGT5LKmM79newU5kTMizYfeOD235dt0j/jPPv5VXW+7B56MqjB5A77cO2dnjWVmDiH5Q/fyiDoYtKbny/bMoBay+9Y+SD94IEqoThNt3mrXrQT/yQlDf8YdHWHgCtPjlEU+COnL5E0T4qYflbYCQN7904z7AZJv2d6DeEq1O/1LvDFz09wb4w/ETv1iBIp8l8VPkH5nyR4Vp1eMj7epM2vNRs5ucCX+h4nwiHn9dMSFyBYop+XxNgQcWRb5l/qWSDn969PCh7ScOrFM6e9tzYC00n5zlUFlBn9xp+2kLTFvUSF+hsWhToCdlbbKdylnAOuHA/LoJ5Fk2RlUv/7/O1fYMwivNB2NZl7NeIUaEDHJCjnTsJ417U7PaBQ8O9hWV0NKLKeDz4EVSm9BrUQ5bTtUa/IDOTZtQWehpxDpiXs4TrrAfnj8Pe1M6XJ+ArndYEL3hmb+CzLFYaSeT1TMiHJ/a6upZB4bQiyz5o17imgIuNRtg4DlEEYXFZvIkYNHnaIy0L55UU/yrDu/S0t+qwvvZk4mloncvlkA0brCvVCmGUrwNLBfxySMP5KTe+N1e36xWkMpvyv4ebnV4HjMNXSbe6OHloZMjaqowf2u0/PbELNomzffWD/GWZkvmQUvD+Xyk0XUvfXgOfvPV1iuCnkV0uN7Vj4Lzbc6HrcLJj8ncKjN41GzECq7y163cI0Mjx4m93dGGZdWTQfqgpudX8CJzLHlCxgqcTkzkd4P1xi2E3eK9w/Utv6P2tN/0cZLtQdJ4Kz0VSLaPgM+nTatfgEJMh1y04abp5NA32c/A33oMtXsrzhkKIu3Hikyks2lVeag3jXoVcc4Ibnx06fQpay0gZ+UGjhWW5YDi78xtzGLQZeTF4CUZuPqKfAM9V6Uolww3PWluG/5feoFtnPY0o0BVX74N+p0VvGcO/f6+dtYANu1nNjsPuxcitJ6COBBuPF5zX95AMgCwHFugoMOBRzPdIaJAs8/Qq5O2YDb4kSiOeFlk28XC9gblWEhTJXbMhE6oleQ5NwoKikUfKG2ik6yR7qjqsu74lRAcKFi7SH4c7xpfTz8GidONQKmR/ke0UBc0t6fZeg6cT8pMLxGlkbYwqpRxm/K11fAxLI5RSZqDy/oQeWQkasSjfdfgw/LFxu5ol/LCsJmgPEz+LviyXRn0ZeuU/hnlbG+JeQId9en9mYOcJCX0FGRoJGsh+ZQJfRzkXHYN0WbLXHWGtZqVOoxz2e7xTtgUaCNPxdELBkM7KefiJJi2oLI/njIy+Zw6HHqyJs4O3jtwOcoUxB5vdX25GnuVLzZthTWiKXhtcmxXTxKBEI2K11icUoVfHRVM1mHOqWmcXpOblv/y7nUb27ph4SKdOI/EGGnmskHo5wU8Ohkn/CDoCd+484WkFS1tHjztADzVLry87aCT1dbLTIFTqHbAYg9LBW41mofBF/849mjTSatginAifpsRzpcBw72OMd+FdP9mFfCh1cHG8DEbnfux/BD9HlXTWQ8EXN5rfQKNcSt1HGMR9+mE3zPnnUNAP292tM0bgWptjN2agRYvd5UVY/MqNunon4sd+rmWHajHjZbxwkJM1Vxg+45a7IwnnhGZtR3XRv1veWfyGmu8KjvyDD2auGTLo0Yi2SCy/ESz0kL6VAKOyfeOToZXryytZUPqB6MV8OEEJppXBp51fgx/BG9X7ztbDEIlK7zfwr3JF9UfImatU3g118gqL+mHiVtXcEVgQy7v0Zz+NvGmj/Vt1gEbu3J9dZIH9LXR/DkNa7Oi9KHj4Se29a1D53I17t6ALa8jSrYPIxw3vlXTIXOZGlwvbMhPZW6Frs7r1qkOoq3zaqBg0ePRhXBaqHpOb2gKpUREzGtD/DntA5hEayR14E5wHLzyOo5bCgLffEz7A8R45zr9wo+smHjoTGpGjya9jhdxKW0W4YY+HrrgQjNUykxGHW9JPK8jB3+t19x6BN0dtGcLg6KYa1svQZ1Z4bQLcfUU+KtsM81W/PLYQFiXuvlkBnW9VVbRBkW6rniV467fYAKM56iZzbIQTGlw1W861Qt6Z81hKYaYAA28NFNq5fl8f9OGqDWY7RiN8KWaRPPB57fS19fD8uevJEtDwtVaOPFQtGSlW/V+N7m4TeDxiL7MfXFsrzRMMOa+yi4bBya/E6L0D1nVFx6YDDrTt9vgGm90LHzM7Ym7sqy5Wga/1F5/tgJ59eq26UN+w4v3ISZxn2paDM7Dlw6rFRWhyUTNBzZ1G5DvlnJxhIREP9IANBzbE+sOuqaz0OU8a0VMWrF6GcVzxrUyn0bdv+p3VoXnADdYTULXQSsIL6lyU2BkAd85t+/7ah0ZkidliKwzYEiTQBXt99MMWYK5XpN5WX8TRzv3hBNcMbl3tAf1VX2zwhyzCzL41kfieWH1yHdzTFf6yCXY2vvAYgQpRp/g4LtJI4A17bT44Z2ntJgLTzb7ttY+mkZeL/j5uMNWCK9Ubsrw+HXAbcnREy9RAhoN2JnXw5zmNkCZoTYbp+qHcnq7NI3BlqcVqBh4/8GebyCXcbw+TzkG4fFH3lBncGBp60xZ6Pbit0xKHPEfx+3TCbJGbmd+hyrTgW+54zGX9sheaUDgrcE4PvqrZK2sIU7k/7S2+jnmwxBhUBcNztIqewbMVZpReaM5aO0x3g0YkjsttYINffZNMeGCRAhdr6W0acbTlIjXQy1ggoA5+ppMoaoJqf7//WYRuVoEpikno+w/vP6rBXRyK7FqwZP7ljZIMGvn4yv5jNYy2peOqg1IC2udnoPOzb9rSmTRyyf5N8GYY1/C4ahvcbtCoWpVNI1zbtvk+g+K/7pU0Qg/lXRNTkMelXUYqB+dyyFVXRShlb5SjBv1dvyc8y8W8qxZrb4Qqna6CrXCfqYjzApw19i2WzEN/bPozrQCNX4dtU4MxnM0idoXo47s3HFxhM4trzmmoxNi0fBPO6R6Tr4cbA096vYEvLoSUf4Ri2Y4SH5/j3EiNPtMNy7wrG/shg5n2Y/46zK3VC9z6cO+Mr8shuL12qsoc3rikGDzzEv2Sv7N1ERbkHt7E0EAj9kouERaQu1yNMQkqSFdbZ0IR/92leVBl3FOv5zXei3y0kgegaBvP71HYeekq68YmPH/TC8tjsLe9SDIRiqStnE+B7/eZt9+FVo/Pma9/h3WV7SmVgNwxAmsU4PndF7bZwmHTJ5KxcKasm3ITCsyvdKdB3fFqvU0fMK+c7TOU4exTjlUasO5f3WcHKLnA/fwytN26sjERmphMh6TA5Pg/uxY+o98KJTLou9CfpSaM7FBOkvOKOdS471V2G7ZtYRPMhOF3887nwWFF4TPsX7E/NyR7eKHhmMpuEci5dxe/BRRLsxGNgwPf68NvQ2suldEMWJL1q5OvD3Xz6K2eKDxXV14gDT+nZ8haQt9rdvaXoUFTQlMCPPP7nVoKvMqcIy4+hPcxAaerclBISGZRBVrYHhK2ga6+rPGR8Gc/58rV/68NBD1uwu5us1npXzjnNYadlaDC5dBP2+HtqC56B5hFLXt2Hy4oX9/57f/r+/n5P6DSukbhSfjR7f67sikaeRwRv/sx5EsNrXoBu4vObW6Gy1vtnolPoz6LnGZtoONToYx06G+QL5ALefyerCqF2tPHztZAqsfySB382nvP4c3/ny8Mf2GZwxyf7zfjhqIz/c1C0NBkiskVujBvMMuFI23RzSVQMXNxbw0UszT+2f6XRo6ULDh+g7ZsBV9+wMMBm3dILtDIvyO9XCegfKLvpiQYMnEvMxMqGvaL5sOH7XUKMss4H9uCcpXgkw6NTeowRFRhvTsscNxbnwhXXTTUTYUWRRZPs+FvnwM+bXShRHHTnakvMLF33mcIqmRYTI/D+Bi+WXH6UCL7K9jjCLw8ITdmBf0Wvng6wh9st8bd//985Y1NG2soWbO+ue8LpOp8chuCrCsXYoTYEOeYT6cx1GR/ZWcJnzZIDNrDSLeLR3u5Q8nxP5rfh6Hsrd+npuFszoSMKE8o4REtbdsDcz2LHA5C/3fFY2awf026ebdQKPmztPyjH9rQOweOwkzLqsPr1oeSBO/wVwehzVlVK3P4OG7olx2Mb+5R65ALJfbG11u/Qa0p09M/YUX15V42+VDSvIFpmzoMpqf/oAPPMTF4GcBx2klDce1Q8sU4YU4OXjOsz1CFir+ds13hwyGHE7fhBfU+nkxoVelWmwdbw7iaGnVDyWHp9oBWuHY+Q7oLGg/8vcSoF0q2lhaKqMAtt5407YDe4ydVXGDepcPCt6F/Vd7rDMi2jv1cHhzOfar6eE8o+ceU3vcCGt+IjG+Gl5vsTCahsKPodb69oaS8cudeUdioZT8rDQ1iL35aZRJK0oy/xbDCHYZa+3hgzJrfafowLL4pIBAmxgeqhMKd75RGLsE8meXsSh/sA2E++xRuyRfQb4Q3KQmRI3BQiPZqjW8oabd9fXMd/DW9zk0Mbn4/ZuLqj31q75fygmVbvs8FwJPNitx3obd77LFX0ILujWIL1B3hWOmECXdfRw6nhhJXvoSz0/DyjKPrImx+3Se98U4oWf+na1APqtcNtBnC3sXfL4/CaumRpe6MUHL+yJXJAWg4sbV/DF5avp8gmRlKvv/ZanIYyk/J7rWCrdZSGo7wBRf/5ancUKKTGx22AI9XM5xfnYc64Ww23wLlCg7+OwoF3VlnbeFM2psxV1g2fJSvpxrx5/cIDkL+qJ0i4/Cwd9eu7TWhZHvaamYPuL7bmv0M5EuqWRsCDRpubhl+Ekquy59Rn37y/3NaaS/CaH5DL83aUNITzKbjDb0r9usHwiH/2IOhUKZ2U9T481Aitm0sbh66q1Unr6oLJSL2bB3b4Zsv3ose0OVNHONZeF+3ei0FliZ81yuAx2n+xl2Q0tlv1Q8TqqycR+Gt3vP75l6Gkg95CkdXoMLKd3uWBuTtbXP6NnjvaReLI5xa28l/CuaMdEv4w5Q/K05xH9CfR94FJkE/razYLMh2UWmpBTrdv3P3H4yeelTD+BF1++5byxpYOuo2sq4rlCxM5DOJQ78rs+LyMOf1jgZ7WOQxdjATenoknMyHjxlJRDkUOaX2uxOGyJY5LcFVcskUpm7sd3108lqoKpFpKtOHfeup8VeG4du6rmvAhqPitl6wJlaRIRWW2yRL58D2Rq59D+C6sPsPGKfRBxb6PWvgctsvFkH4dE/Ez71Q/VZHox/kdX05ex5u/1otEQk/m8nfWzUXStoCCtpZ4W39bUy8cNl7728C737h7D/9v+u/85yD1QzVejR4r6xuz9qFUHKnWj1AEGp4leWKQ5rEoJ8+XNHN1j4FA6RtffzhxyrhuxdgcJhVxg76MLK9tfazHjT/JM9jBF9G5CsGwav+hm13IEvsAud9qHy8WL8Eqt/k/NnkEEbWvDJx/QRPTd4Z+AK77cJtOB3xf63XzLfCyEcSbbugUdojU32oY5EtoOweRpr8+ZM14EDclY168BT9AxU32FOcKnkLMr45dj8Dsg5u2JwPU/6qSdiGYp30vlWusFO48pA39CmyPFUGlehUbo1CYY5OpTkYKBv5cgX2BBd4e1wKIzt2d3OchQHi3LkU2NASVfkA6lXpOAxDyfympWlIKmyS/sFHNc+EaPFhZEZh6NEl+Kuaxy4R1nNz/KiBbbUyvv2w5nAC3xi8u8L0cA4edPkcRFcaRjSvG6ixw54/tWN8kP6qyD5jeHKcNf0ifPz7i1Uc3KRczZsMRf89DpSqCyPt1yR1lKCgSxyDBjy8R/K7G9Tz9np8G6rRbQ7NggwfpvYVwsSW7x+3NISRaGODFE24wvXQeQ/8VHvQ+AxkTP/hkwI5/93RzIEDSbari+HdL7sz1JrCSO6uHA9tKNa7VsMA8sqvuHjBK/2bzDMhH+kSL4B2fQljFXCbchmHxocwEpbN/FUXbjrh9MDw/+vpkpPXIL/dHdvX0EvXXvkjjPGWo/sCr53SXHe4K4zc8Ugct4KLtbMvneCJjQcWE2FP/bPvn+GaqXkduu4w8qewbR07rHhcM8EHzQrl9gv0oU4EjGTE4KX2M6vlIYu267kjUG/WZzgU2ooONlyBbSnH796AWtzRPS6q4WRTbt6sF/z28eOaIHh6U/L0J1jSUDYrsjWcpFbYrt0Ev6mvlVOBtpEzDyma4eSWoGxHNKzY7TyXALMVv7Z2QS91Ch3HznBSJrtBXADuLntBxKBMh6+9PPxROnY1Ti+cXKeqlidD9bGQz9kwJ3y4ug82sugfZt8dTjoNh87wQw2lq8kbYdou55+bHbGefm9pDXhSN8JRD45lTQo5wCtHtZhz4TVH6rEhWPBz3a1JKCHzsG0BnpfNE7dyDyf7J746O0E+P+H7ntCeQ25XPoxh5HjwE66WLpyehv105tuX4Ia+7r178sJJ2AO36kMw231J0QruzkhbDIVvd/urFUB2m8P3K6Glo5rIc2jVlhOuUor4ghrLO6GWcWuAPixIWmsSAX9+fFv/AgZ4NWu9h0YrbQ8/Q5+gIOqOGqy3QWrVHhjF0UE5BBvVCkJi4IGiyuXn8EdRY8hbOJHbt9wOu/m62EW6wgmH2assGfjl3uOdKtDNbpWaKzQ5XPEpGa73Xe2ZAwdyrBhLIPOHFsffw+EkcukD0woc3fclj/VXOAkJdq0OgRPSJ5VroWom46dGuKCVd+4jrO29eEtmOpyw6b/VU4HJ7wXHdsJKodiRYCj/8bhpA2R337DcAotlBu93w/CEBEeDhXDSVbeG1xS+E42vt4VW2lMRUZBy1Y+uDLr4kdInUDOc36kRLhRaPHNmiyDbv0hf8ILpe/7tCIKR1+/9egAPRbN87fpfKZXkQdg172A5CWVSs3vMgiLIPNONCXt4lC6W3gPG2o06ZEHnJ/+ed0HOSdO2QVhQVvZzEq6RMjrx/lIEMe38F9kFDeUrcwbhdPKUNM/lCKLYmJOtDbnvFb7cDxmkngwehZHN1qP28RHErXaY2wNymlLVA+A8u8q7LPiTk9GlBa5yHb7UDbc5thcPQUntOqnLdRHkIkON1w14+npNTQYcquP78Q7Gh+jpsdTDhaQYXhis+69zAzypbTx7Qj6SdAxQ4/xgUN6jzRQoQTH3b4EDftks/AqR5Oz08Wwx2HJNUk8RChHbvGDVSBL146fRRdhWfmEiHnJk1jzthCbjVas3bo0ktvkvcuTh26uf92+HJ28ORSllRpLsG6VhmrBKMCpEHwotuFknwROXq+gHofMO3uVJ+N494O8/WLZx8DdLViTxffhmUicvklD6lqYMoezNHTMW0GKj22IaDDgQv2oQPl/ZTz8FNXTYGZbgycInLTUfIsmFOrnpBugclsb7EUYcu/Bo7cdIEvs308kI8m0Mi7CEg5Me95xh6phthZnERSLleE7AEbo3pASchjUVcf/S4BTLs7Mt8EmPVmcPLE5/uWMYCrRGcNjIR5Ogcm5BdzhllSt5DqrMGdvVwvInxRa8CtGEl9rmJA63MDJ5K0NPgWOaDqrRRKAxxcgLHtk9YncBdp+XelQPT9FH8rFtjSYW8uabBKGfiKqmDLxw1z9m90g0mRAs3WkC3Zn+DdvD3fWyJnnQ+Yxv2gDUFdtxaAY+38OxRDcaTV5PyH+6a3KF1Ecq3a6AofS6dg1Qs+O8xnrTK8QqPvlzCKx5a58WC1+OqrmkQ8f7d5ZeHrtCBkS6X7fD6hCZGz9gudHwK3nrK8RYh/luCNz264d3LNwS1qGVDhOND3iWbIslvYfFP76AbSfYdnTCwVSnVuntscT+b6S9HxTv4HkVCd3eFG9Ogkl5Apc3yl8jT2MbXsjBWlnq8lYok/hq0AZOMwy9joDV03Orr8FPidzaSTB1JmgoIP4aYaK8DQuFYlqy4jHQR2XpxkM4EKG40gspawZSRuGhpmzNeRjERCsWi4wjZXRkpyIUcmZrUIfVc9lTLnCl3mMs4f/PX6eeS4Ob1btW58NWubTxJ0PXibnX8pp3MCncS/krFP07WLLhx3Wi2LpXzB5WaljoekNGnyBHKrwnFCO4zeAmOb7e7aU+/LrTwtcSMnB8kUmDCtN3ewYhG9l/aR72PaDTYN1/kwTt/Obj2H2LFClFTZ2BNrwGPtHwP7Vb8sw= + + + + + + eJzVXXtcz9cb/5CUotwWMvkIiR9qaklux6YiNpchI3PcmeXWZm6/HAwzcsm1zDqmlUuuGZnfOGJmc0nlssbquA6hyJ20X+fbt9ev3yvp+/7u8vL808vr5fmez+ec8zzP+3k/zzkfTTNZyOMnd4npaho9lHQf0dMcl9zO15NZ668g+qyXw0VIzyvwFqKnZc+BnlN/l1Tp8N+/ovnFa5D+O8mPET1tX++riB7tFHEB0SNsTIl6PHqGRQfgd+XpRb8jz6O95vYA0ZONrdR806gblsjz6kODoX3CLW065I8nKy2G7LBw/BFplyD9NtXU+unpJ3KU/spNrvnPo6/dcxv5PZbcIq80evr9Ptj6miiiq6UXsp4vEzn7oTu0T96p/hv5n3+zyDBoHmTIrZrI+DRmlfJHbIdVY3PmhW210PL1SYZltfy/vIJ+mQC/o7cd6pOvzxJ2l2rfvEjIZ+ddSvM+JPII5I8K9dd6WZmiz4LnPiLIQKFxaj7ZqY+geRUnt5VF3pMsXZmLjKfFn1Rxh3UJyM7/K7lHeWR83jciHRmfZ1pD/le+F3Md0RMN8qB1ISMbQXo09asb0Hix954heizXWuElsXvNPVP0dUde7LqzauUgP6c3qwDhIPmoWzVk/4nq/aF5pjWiK0P+uNI4aP/pRx88ydeTQ2weIvp0e/YdRE9+dAHCl6TiNAx/G8d12jb5r4jjf7Uwu8Ah/+Rz84XDMFxYIDJ4rZ/KY3p+WA7C8d6Zz9X4u2J0hRf6NWoJ2eWM9Z2L1UvKdIbiXK4llid818pDjZfZq4NZ+OnyUMgfijN9X8sfl6ZZNYHi68Qwk/x5oXiOVs/LBm4skh/pqVFVkedgzx4pvy5tJYSPyPIPoLyab5uhcKsc3y4LGtc6F4rf2poa0Hh0+BSIZyHe06G4In36adC+qvQhhv9X2UN4nNtdL5Z34JufXkSeQ5RvCelp2nFbyA/MGF4JspsmZ61VvtWgA8YXTKmn7Fd8klJiXBBxFso/yiWRULzXN6RCz0e+WZaD6DGH7yG/RhyCsXn0CFLzQnr6lxwXE3d4Q/t7tqeyX2abWyTPF98FKn6GVK4NxXUev0zlA/T0viJ4laXxChCfUd0Fyru06EQs/u06aMhrT7sov6iH+GPr97obhJvJ/DWZkB6ZD/l/rR+2P+noCZAfF3u3ZBc3HjuXpOySlLsJ7RN64Bsszjv2geI8SaiD5Sl1V0H5H//KTq2TeG4D4bJC+SK5PqR/ZHJtyM9sy3wdws/uMyH+U2TbQvGSrfaB5oXYzi52P79MxGAP5V/EtA03EX390AIovstFaVAco+mRkD+lP82C+BVBsqF5ZYOOYX6ppQvkd8Xu1RAPKfoeNMlfiS86PTHl/xtF9h7yJhR36xyC8lfhNsoDsqPn9SBcJusOKHk/h2ZBeYr24LGTKe9Bne2hcfiGjSXuH/p+ooEn7ZMB2buW2N6kfUYHTIP8/P+LrOPw3JRxjSIaNVPrqfsOUs/NV/Qw4JMrU+pB+zj9LoRj2ZjfoHgg3OfXgOJkm85F6ynp44vaw5odRXARqZ2l8DW9txyyUy1+O+S3dPvIp8h4+qUkyL4121lF4qOwW6DqxuxmVyyuJIxXcYVYZ2H9D0ZxrTXIHDvhPcJLtZ957LmuEJ6Z2w7iS+TmC4b6o7e3sju5s0dTaPyFYW5QHHD6rpGq1362Stkt7eMH9UsYhTIdyzs7WpWI08mCExCu1VLcrSH/kLgL82OT8lR+I8amQvGDpK1WeaxcuRfiGej8zVj9KDlL8W90SxuDHw4uD+Wpov5MqI9Bf5hWrF8Vjnug3yuUuHoYzpxYBqpv6WU3qzyDnXuA1XdPdIXGFVdjDX147Wa2g+JoLWdPyE6eRqp6Df08HsofyNFEiC8WP16B5leejTH0MxxwfQ2yryYO0H4U6Z5F7ElWO25S34lR2KpNWD17akPIDljgfgzPbyoP1Tl4kD1WB2rhDemJYeUgXCbT7mD27fysDLTvTh4wq5/w7xLh80Xvv7U+HnSmo6r/9Z6C8UK7d+uQHTbLw/pgA32xOrXTVazvLDMEi+MxC6F+UTKGQ7yJtjQE8k/63T0YD+0VgOGCLfugfIxnrMPyxgKhi89C60FzvmqG8ay/QH0AWsZTiM+gvVIge2IHb1U0K18J5FDckIfXQjiAlLOwN6vPxHrxYLP6Xa8PgPykUegPHqoewn4Rrcx5Drmi9Z/Ce5FpMxUvI3eP8IXw6508G0gvSqr4Ty0PvAHlO1oraFwtJ1jlB/TCAgdVN/b/EaoTcIsjJs2/2D0dq5MusIH6KNkCZwO+qiga/Bn7RK/S01Gdg+hfEXoeo/BBkyC+kTwPgHgIbcRVrK6+3B+qc9EB0VA9jx/xgOpAdNcnUN+qvi0HOxeVnlsq/0eftoDqvnT6LGUnPOcI1o8Q7obx2VY2EL9KBl6D9gkvn4j1OZcPxerTe5cY+hW2JmN1ytRNIa9iv/GLhNeLVDiAt62nztnQOe5YfvBXyYMWUDx+mdD/XGqh+KaHB7G+igJhxyaruCK7dMDw0IMNCscxOaZkXJ9KIHzJug+E8gX9/ELIn2oHZkB5sOgeZRLfz3ZWg/rO+a3lZq23PGdbol8VQadNypPZ+C0YL3ZjAcSLiTJToXjCg52KHU8nX6vzNCIsHcMlBUKn50LxShtSAdITbRoqvo4HnFXrRX4/Au137roDmk9GRkP9HYVy/xd1rlGOnd8JyhueXcL6wOtUKHJ+ijgGQPkbq9u6VPNNrY87QPjpxpdYX0pbJ6jPisW6QH6WnhoN1UuMol98o0i/HfVsAfEYrNtG6Fyc7vY1hhcGx2P9bJOOYjzd/hrFnxN6ibCjZTH/XCD6BYHZ+byNLSBeuGsQZC+krBt2bt1tnIr3tPGXpapj6J7XIJyk358CvVehftebEC9IZAODXYQfgvq09avvQHZlFOZ3Bbt3wi8H4pdZu/eLjfPyYDC0bvL0VKzPcvRirL925BP1nHql1Sb1TfBff8POG823N2leyHX/utB++L0hxKPTVrXVezGXLlC9UF/6COv/MlPko7Kfvsp5Nrt+M1DNe9xG7FxlKYXsHGySnfC6eUFm4fTVPtD9IKRcJ6ivzCj6mHWlusfjRcK6lqsC2U/7GKzfcNUwtS6k8h6obsqlO7RvxODuGO49FKhwlYwJh+4HkclLTcqfdN9YDDd2P1NiPNFDK2B89cM3FC9Af24Avb94tB/S029geI2dDDDE6foWWH9gt4OYPSSPKBK/yO1ALK74JkP8jT63i/I/MmuFv6rDTLsH3U9mFNZ6m2H+nm6C6m9G4cO8a5nl3xyWQjyCfKssNI/ksiH/FkEMq1tvmwDhukL9sHEYD/XDIqh/Qbe6o+yTnUrG/KNfCMa31Z3bEMKV40Kg+gZPXQLlC9QrEzqvK5LmFHtehEQ4Q+tb+Lu7vjarXisdoqF1pl5+EA9IXcOgPkz6U0toP2suDhh/N+i4u4GvTYDmRx+8H7vX41ei6uVkexzUL8s29YTyaOLdq1hemrtOxPod9u3B8sR+Pn3Nwq8fJWD89PIqEB4icRY+ZsXDXo0Dofg+YblZ9T7JekJ9ajzjNISH+HCrIryQrOeH3SOY8m7JOEpfCuURuqeX4ufF2vFY3Js4C+IvqeUIKF4ymzSz6nNk32qDn8mNUPdZCC0AuudOL5sE4VrZ9BMs/jYdB+UP7OOq2H2OJ3IwXichBOsf3VC92PH0fg2h/Jqt+xTrR669DNqXMscC8r/C9xiU38ntnbHzmmf2Qf11svVhaF35GOzeVBHRBnvOKv5Qf4FR6JpGUL2YHm4P9VmK2HjsXpS3vy253tA0Qb0HXWkP7WfdaxE0/9qo7VgcCc/A7kEIagvZufwgBMtrM+9BdiAHRpt1LlmmeKg8UXrWx/zM1BtY/4RRhu4w6X5f4nEA4p34u/MgPCqTIrF78sYPVfdiaSPnYPfgDPVV+Qq/0xg7x7Bzr8IfPH4U1qddIPRYLShv0td1xOrI0SnF5pdslb3ibfVPe5hVj9XWjw17les7LxTnSdP/yfeSQ6sOL5Ef33kf+z5HgYhRo9Q5OTIwCovD42LUOV9y3gXqU9FrZhn6d8cOgu6FF73/hfHVV8PM6wNpMu2V3u/iYvbYf/L5+UYnqH+H+Duq8wTscIRZ/YnCvgt0L45RdN0Rqg9Qm0TsexsRI6H6Gs9rh53P6RsLfR+Av9ccquvqtZpj8XzZM4Wv9DxXqH5BV0yA8Blp3wnjb2q+iX3/4mx9iBeg8wLMOh/OAxZjOCn0KIRveKNmUP1LdHyK9cXbOUD5D69aAzvnOeR8G+j9psar9ZeJDlBdkzc4AeUTLGwnhi/qHCWQH4jvD/XPikGtsO/khKZBfKKcfEbtU3LkW4gPKJTOlKp1jbKD4uGLRO/0AzT/tI3TWyo/avs55MdF30Sz4jK58ATrpzPqy9bQOU7pGorVCfuPhfJA9hz7DpgMP4HV6ywDivVz9OY1iO/TD1WE7jkRMWex+9DD90N8AW9YA+NB95zDvmOT3ReK03zyDYz/PjYb6sOj1x5D9XjRLa56SXqs2VQIV5MhH2P3y239FsLF1OJyifhEUB37HmTcYIjn1+anQHrSdhPWd+NxHjvf6HIXuoeMP9Sw+83dL0Pj0Yj6daD9vfgedF5dG9gNu5+qZwUoXun7a0J2xk8/hs7Hs/TZWJ3Q+RB2L8J0O8O93AejLiHjskansH6aJ/+G+FV9yk2o38AoouEQrL6+0ErZMb/92BWKq81ToHtnyIAy2Pcsf47F7gEKDYbyZjmuO/a9kG41m0PPabcCynu11Tuh+WT2WB8RbbsS+/7K29HY91wvrsfs+PU5EO6TUaHQ98J4qg+Uz3GvLtB4RpF5Hlje1NoC43ey90FxQOuJfTeZPUvAnjPDHzun5huP8bu+nbHvF65IkoieHBAF9bvTypUuInp8Xl2sv/77rVA8JbneGSbr/QFncsxN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eJwtz8tLAlEUBvCr0raoVmWCNrsWtQhaJMJFEGrTE4Le00xlmfTASivEG2NGuOi96UGDtlGiRds2Q+IiLET7AxrGVa3K2gRFMd+0+vGde+459xJCFEkapIQQGruEJNI9pKseRoeh0zKiK+9WQDWehcq6axTZbxnDuRgx9HC8rj3jhuqXaQL9c2ZIO5KQP9MgORUF3Pu8E9HnfJnUZe+OKfTZOGj/SBg5XzIMJacx77xkmHN7sc89AMl94yzm9HA+5PEM5B/+LQp+2CVCcjsDmVeCai4JlXx2Hvt/3AvoP6hZRP23AFmhDOm3aQn1cBEynwZpU9nIx+YAzl0CZGLfMrIgQbklsILs6F3F/j0BynWtQcypqg7hHZ0cZNcalCsDazB4AhVbCdKGD6h6ajdwT90P45+xI6g0JxhsS0P71eMm5vrro6i/pSDdSkO2fWOotMcw90mD5PnVyDbrDvqtHOS9/XGYuojTP/m8pjI= + + + + + + eJwlUV0og2EYfX0zpJZSVi5ocWHtgu1GLU2flOLCmihSaxcTya4krvRRJLWUWhmbjbAZavP3zWRt/mol7hZqs6TVltqYJaH4znt1es5znnOe93kJIWRcf8b+g8ExYAPag0sCcpbyiICJeNgrIMtvOMD7ar4EJEm3FXzQhLmQpG8F/XdTSEDZpAJzoUoG6KyI+9Bv0biQc9X0A//gwiH6PfXQJZhR6hMpo77K0ij8Lo3QGUSdMfAZxok9XNc85tPSHfStXZjjsiMXqANPNNf6jFznlC4JtEuX4Vus3kfdf4L3cjPpTezB127hfdrBY/RbtUfI9UzTexSo4Es+77eBv41h8OZhP/SLs6vQq57gT8Y0CfinDuAXYnrpvY1Relf9yzr2UciRz2U66PzjDfYkYZEb+vYSqv+20veYk9DJvLE1upcSNavuhl42YXlALW6mfrpcDnyd5BX8/CnNzWqAxDN3Bz5QuIu8PP+GHJd4D3VKTnVV1R+Yc7fhTqQhlod/NkH/sch/jj2Hbm3sH5Ics48= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eJwlz08og2EcB/BHTUqiuHF50RRJWg5Sq9de7eDNwWpqE7022WQ1M01GPHu3af4u78qB0pvdiELiQL2XXcgiBwelt2GHpdQWBy56v+/p0/f3731eQgj7VeVgCSFMVx7SZGxYU7A2C8iKBbI0PAbtMhT23C74kxvH/kDfBPpWo0eTfHO6ITeUsy4v5vnYJO7mvT5kZ8yvqUiN05rqhwgpMQVw71mE1F42o881QbLfCwVzCao3liByywFkugdnMUcLIdxRbHOon9TOY64nBeUdQxj1TB2kfl7PRg9U24KQcBKUj58WcC97tAjvS1B9Ty2hn+GWsW+4gOTqDSrlHVTfe4RMjRjBO3a3IR06hKqzGNG/4xJRTxchcVdGkW8dkHEWoNBfH0c/cRbX3/EL2evOFcyP2qAcyEH1wZSAxvVVzJnPIa1+0a34g8IIt4bcMAXJZXoDSiUon0Y3sd/u20J+5ZP4z08blO9aJfYfbJ6gMg== + + + + + + eJwlkV0oQ2EYx1+UGyUX7tycCx/LBblRrHFEJBcrJGs352ZrKblhhtTUWsP1EmpNTmEz+2I+Zu3dlNWyzBa1Jh1jmUjaLpSQzv9c/Xufj9/zf56XEMLoLvdZQgj91TlE5do/S6KyFvOzqMTGp6CtoT1RBXbdifr064OoTE8R/UJL0o26two/4puBW1HtheoIuLXhMFSv/YYGDjPIu2Xg0j6VB32RES/ime0oVOFEnHp94NCUMoZ5w3L4ZeZdd6Iar8gT6vtHUc+Z6yRf+mXMITMcxV4fNvgQVnvhT+g24U2G5Anw4oPgcbES+GSB94HfvHSD+F99Eu9KPgiewYG9jfn3LPKa8jg4srgLfrcS4LNzZbgj1e6in6tePEXc2gmlpjD2Yg8ec5jbOHUNfwoL+LQ4foK+nPUYexqqkGfUHO7CKFVHUNN0HvUDE7gD2ekIwZ+8qQB+16R0n7Ua7EPU+gvw7hvgk9kYO8NcFQ+OPfsDP6y/cA7uShBzuBd7GuqOSv/W5pDymlm8jcUvD/sP/gq7Fw== + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eJxjYGB40N8S7cDAwODgopwAohlEncD0g0MQesHUJjCtcPYQRNz+DZg+MDs5CUQnuFyC0H+nJoPohs+HIPT7R2D6wBvHVLA5Zx6DaYfExWlg8QtJGWC+T0smmH8lIwdszhvBQrD6cKUiMH9DZSnYPL7AcrC6os9g2kHkUwVY/ItAJdhdN4UgtKdyFdi9FeUQ2nMSmH6wcHMt2Lx6rgawPu5JjWB54ZNgukGutA3M36PWDqZXJHeBw8NRahJYfpXmJAcAIKlR0A== + + + + + + eJxjYGBgkCh55gCkHiyo/QqiFzicfQGiHbqjboDFxXI+g+gDD4Mvg+gGEUYw/WCH+HOwOreNYH7CfvFLYNpBBqJvUTKjI5BWcJgFphNSljOA+Q9SwOoYctwegGiFjLXvwfQkRrC6hmL1q2BzI6tfg+3zF7oGdpfWyldg85nU2EDqFvjzQdwx7QzYnAbnWrA6Bdv/YP0HBKrA9IK9b26B9Zl4gt3lsNz5OpiWOvkRLD9tFlhdgnPwFbC7dieBzXV4+gHMb9jPfhcsr1x13QEAW/JWPA== + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eJwl0MtLAlEYBfBL+Q9UUIEh6kgLo02t2pSoSdEuKxA3k2NYYVHaw1465djDFoHSrseQQvQAQRctJJiSKLJVEVSbBmentMmglVCeu/px5p7vfjNDCGG3rQ4T+XdPcFYlaj1ble9loJgzQ6npZBS9gwKU7xTqIedCz5bkMP9zC+Wybgx9DUM94qD8pEBeY/BU1ebNkP8tjuMeOzNZ1aQ2Q/E+R3OfQvODxYs51QQkdtU05vNWqD1zQ1EvQKlSNwOvdZC8dEA2OEgNPc/iXPUO5a4CJHzMh71Znx+ZxKF0nqZ5f2MOtoepIzFqYw6ykeQ8/R/1C7in2QJFB7NIv6MA2WEF8v1MAL1uBYo3Zchfdi4h9ySg3PoJpdMKZL21y9iT5SAvhKkXGShf+Vfgt30V/Y84lGzJNex7bQgimw0hZLePRy9Qs47nU49QmypC2bgr4P4vVwQ9YwnKntwmei1tWzhPpaE0lKGZ43bwnm9FyB6XoMk6EIUJZ9T0B4yNrxI= + + + + + + eJxjYGB48Fn6gAMDEMz5dxBEL6iW3wSiG6L4L4FoBZ9HW0F0QuaSOSD6wc73C0G0Q/uU6WDx+1t2g+k5pY/A5sz3A4s7WCmsBtNBTgvA4gG688H6zR9A9DNX3wLrC1p2GCzvsnYS2N4cRrB8gpb2ZLD4c+5FYHcYrdsIdt9698VgdWlGYL5C4eapYPPeZR8C60vqmQLWV9u7Fkxbzj8KVp9rNQ1MOz4G+88h/MMxsHuePdoJpr3YwfYvYNk0Dyz/6+UMMC1cuwpsbpHaCrC6hg8Q/+zy2wKiD5jfXQI2lz0HLN7A1nIGTK/eAPFPdglY3GHymV1g/k1tiD84/kD8F7RpJdj8RavA/liw2RDs/wOS/LPA/os0OgXW17dqEyQ8GMDqGByegfU/cGw4AtanwQbx36sMcPgr1M8Dx0uDx2yI+I6pa8Dqmd+C/XUgcsJNsL7JIhvA5v24DQ6vBtWtM8Hq6hvA/nswfRbYPQp27y6Caa9ecDpo6JoxFyx/Uhvs/4SuJHD4OCSybgabO+0nOBwbzlTeAetb5QlW9+CaIzg+F/Qy3wfbW8UDdk/Cv//rHQC6FLyb + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eJwU2Hc8V18YB/CIFEVmifSzdyKjQm72FpItUUglUXZm2SmrbBmlRIWssjOi7FVCGUnIXpm/T3+9X/d+v+733HOe5znPYdXyYV5B3JXYe+xruSbUjFwINoBdevoVrTddiaFJz5wvUCD1RcIQLLjWHzwB89Z4jh1wciUe9l6aOQt1hroGjKEvufpnK/j0qtifb+6uhD3v/PdROLmjuOMP1JR47iLk4UoofvnLbg2f6+9ivAbNvCO74uAPhemgFtjFe8KzF87wBzn8gCyWy9JknhjHXwuRfdD1zWcOJkhNdXpUHn6KMk5wgxxFZBF+cHzlrV8obHSVpf7t50pIej0mn4c/0pY31uBV3SMdvP6uRPmWdao55B1kvZwEJ5gveNRDKquTTq3w86eD9l+gqOHmxSF4muyX8QRc7ejWXYDaN/rY+QNciVhFylx7eH6KeOoMNwu9kr3g7fOMPs9DXIllv0GPPHiwI8flHZx+O20+C8+M/VHiCXUldGl8xPThxaUXR81gc3IzSwjkz1f2L4bK5157V0FvlsOejXBK557jKCx8SXH9D8wRenBlGfZ0sNhsw/8IPgOhMFdiYY657go81Xil5D5MrlUtfAT3lU2nf4YEc2UkabgrUb/xI4IKLpDvDmeAFaapdXciMZ7J0bpASJchUv8A5tBFNBRAHflTTb/havWT5iNRroQU3552Tbh+rq7dAPJmB3ZYwCperU5bmLTm0RsDU6Op86uh9wpdQRPcCGB92wmPnBQs7Ie/meSKfkKLw0bF01D6CUc5S7QrseY2P2MCs+3U5qzhSb+n89fgy5pdi7dhwY1T6+mw4dm7jZfw6y5i6y00Yw8h+wo3H/Jk/YWvrPqek8a4EoHm0dlU0DvhWYzwY1ciTeNYnCTU5a1MlIOBsz251+Dmn4XTr+CJxTr5YijJnaxcBav6LT0k4lwJehtf79Pw8qGn/irwYP+fxDtQur85qxz+N3Uqpx7K8ua+aYUatS9qFmBDr0TDBnzM1PCJPB7v1zcxLAbzdievXYCU3LbbdvDnNUkyJ6hz8SFrKgx85c3+HJrwOvHkQTk6P7lBeLldw4IhAXlw/o71YUiy+60dD5T7aBdsBuNyPty/DIfKOKMd4Hia7qtEqBuX2doOaUrlu/vgPPlY3whc8474MQVFuGTGlmD00vTkFuzLeLdbKNGVCEj9anQRnrvbZGEPg2KrLjlDbT6jfbZJrsSjQ9/pHWHByauH3CHXRptqCWTWylecgf5DgRqrcCPdUo8kGfGi/JhqChItG3RL8GuA7aEtGMyufIIj5d/8m1nowKyb65eNYA1r6vWLMKzesawnDfXAlrH+O0yUqmwdh4z7LHYwpWM+uM2UDCC/uZqOBVz8IG1sC3u+W/X3w3M/ksd+Qu/9g7PTkOUV3SH6DDxP0FSbgJwnW43U4DMXVWs9aBxFf/JQlivhblyuxAnZ9K7pCcFOBu4oY+iffuH7A5g/rTkVB5Ouyf1Ng9XvO/dZPnclMgJOsFyBiXfS+ZzgcxNvi0fwXHB1zDtYp2SS/gHellh9/RkelnyYYPPClWh5E/b8BqSwCC9yg9VFAxtP4cnWcoVOePHFim4/PFMkafkT6vy0id+T7Ursma3MooOxwmxFLPBbU9VePTgiGWngAx17hS8Fw50vW50iYTij/cow5B+X2zUFl/4cYlyCFuTvzzK/RL31bA6XhfLavYnKsO3cWLYO7F1dLwrIwX3q6vpw+NgwrCcWKtwdZ3wHuylmL/+CtMbTt2eh5eDcvb+QVaR1xSYP8dJhRekIWXPWWd0hnUi0bTL8tM30pRO63D5rRp/vSqSzqdxghTxb8v7cUMtS/bkUXB42eE/APUk2LWqQwv7EGd9/n7d9mW6Hr7WH7GkKXInvlD47dGGMoBCDCTwWMMhrDZl8NLY7ixB/PJsMA/Ab+VuBMbi/IOYxfTGcGFA2g5OC6bQukG9XMa8P/I+5XTYY0t+0uk1R4kqQfm0K2w+n3U+kM8M+/ZclHPDgHyn+s/ATfwdvMGx29T4dCUm2RQwS4JXKsasZsLBWaDat1JWY2+VJ8RL2+7ewvYVcZyuih6Dbp+PeMu9cCeGNvZRX4YJjJ/stWHUk9eQdGD43SmZRjni9Zs5mC5k4v0k5wu8MFrruMFNVuv0ZfEB3yqAfPg7fa0BWgedLjjjsgzoslcFM8LDMk/Qj8LeFP41+NfbDRTlBM6hQT6pyGUZ1N1k5QEqXIx1RUPTWgfUWeElf+eoC/LtqFrQBR7+5ZZDX/BtvfCU11GhosVOCd/Qdlp2gjkELnRfMizkucg8mXPcqz4f5bCR976HLvrDlWjh58hB9C6QvEk9fh7nXzgQrfnAl1Bq4NuxglyYdsxM03U8u6Qkb+aoes350JUKFrIq5oanjnt6jcOpu0m0zyNI2s+gL7WM/MYTCpYQc8WiY5XP/wOVGvN+DKSkHeOTHWSNX+FUmdi0TvqS3T+6AwkK7K75B33svB0fh4n5Bf7omV+LezJ90FriTpugDF1zy+GOrB937v+z1hVINfcIhkGFhSDsKLkuk/8n4jP3H5ztNLrSg4hArgkSr5fs+aPuCTGkbXgl2sd3djL7qxZ8QWmhy9TC/Dxye+KIRDL/lxDtEwlHTHNZKSP/n0fMRqK8a/mkKio0FTi9BA24FFZN2zDeF1DVrKHb0WOQ1uHFTjTsS/sobHayAZf50ZB/hyGMl/nZoOXdHuw9KPnjvPALtb27FTUGSDa2KJbhpkziyBS8xTe/e3YG6RKl8lBb6yGfoH4KyleTunPCW7/UUISgQ2PdBAlq1af4+Df+7UEutCq+InRHXhWfUPxibwJfP1H2s/6nSm3kNKt+50XQb+mbtmvWGZkwZjMHwe6OidCSkrpm0TIATW48DM6Cnr1pODqw5ryRTCT9cJLH6CO/m1QS1w93KIbl9UP+IQecI1OoPLTrUif70yhMLNcha8+auHly8UJ9tCls9QtOtYUF69sdrMJ2mbfo2JBdrpm6Ht7+wTQt1uRK7FvIZJOGGnqa0HDTpn7qoCnkaHgbrQuuVk69NIOP18W5rSJh83bgGx02iOF0gXdpZdR9YLcRwMxhuxdBRSPWi3563ESHg90dVhmqQS05N3ReSv1sILYZWK5EFVbDQU6K/EXL2WFuMfUUcMysGz8Ddmfz5q3DYhaGfpA/70CEGUnnYlJzUEwpZTg3tiIHP2AQFk6FTQFBXNbRsn9xqgk9sDfi7YHe/LB/VN+xvj/dInIP7ucovmEOGv7dDbeBLJvHCG7Dfa+W7G8wSrKL0h/ScERJh/+4zlYV3wc+xeWZs/VhXq69BvDDbdVfBMbjefWLwJJS947hHAd6+niuuCZ8+m7lgALv4pMIsINliQJEtPMX3fcgRut2T3OcB6wWjTwRALpYl63AYr2/2IBbufCYZ8xn6fhqK3zmA/fr9/bq9sGPx9BwjvLRDYDsA8iweEbwPb4qyGD6C1gV6x2vh0uavS/Pwv8uHI9chKZNROdmgK1ESeoL6z5Ar0a5WKrMMbc7JXd2GntlN8buHkddDd/LkoPqKZqYPpHLk6AyGweKbJFGwQXHgWCJc2hHl/g223Uh6PgojBXJ6/0AjBfUPLCOoE9QsH/XgJWP7FVOoMFvBcxkeUlIeDYHvjQrpo+GDEn6FJKj9aupBP/yUMVpLP4p96FjGIivs3m3LxQN3HT12TgR+qJJ6rfQLfQ9byw9tSNF0hc4Iyr79QBn4T4MvO99CZZNXEuXQJDfEth7eaOXI2DGB9XXV7NkD5xw899BD3cLXMqzwxFcjR30o/OT0wVB4cKpYIxrqBUn6JMHvN9/lP4WkEh3MJfDJPhutapgmse3bBClzk992wm+bHyYoJ12Jsz28wxpwb9Z+JgN4tWFLzQI6S83fsYXU9Dv9Y+GBTCnO79A994AiwxT6ApPbbofh4/NfcnggbwYxJAIHulynw2Bc1CHOWBj4pMYwBeZs3QjPgrIhHDHd8CmTXiH5H5wfDh05xw4b9gma68Dx9n22dyDdu1NJgbBv/lr7A+jHksRkOPdvPyLVtoTBhtfvXYHUcwNlTnC2X3/RE4qxtAreg19e6lhHwPGI7oTH0LrWsuMJ1Cn5T+8FzIsqCsmHoZW61e/h0On51VpYuj/uWAtklFCw64UbLxdSf8BNms1mmXnks0WfUhCUWZ258xCe+ElZFA/puQWn0+GNm2ZyffDLUprrCDzTPPV6Cr5ekRlfgnckdzpLLmAdmE/UX4df7j0PK4Zveq7XVsEJjxObjTDMabdkJ3xUPuDQD2n9s2l/wm3nUPVpaF16I2AFyuuZlO1YxHt7kPMfWkGdfV1pzQmlT/qkCEHmg4pfJWAWieAbHxjWtrunEWoa8NF2QkJES7Mf2lu4Bv2E66oJr+lXUd9dRydYYf/6cR4eqNUdfFEEkuRuFYTB2xb60b9grfTB1llY5zBMuQb1wptvtPxFHfp8IKcXXrC2Hf8BI+iO+ymv4TmLq+l+sGwu93sofKxkxxoDf8zwGifDVpXijtfQeymQphTm/DXVrIHm5yRDPkEGoabSvzCw9tcLYh3nh3sUv9TgeJIQlz404pM87wdzVD2jQ+GXyrq2aPjy5SLxCd4rfju1Cvnk5QRINxBfnK22VPCV4lFND5gUvTM0AHaeHGwIhyUFzsU9kP4X2zH2TfT9puccBOBL3gc5x6GRRuuEDHxSz8CvDINU2iV1IK0T+20jqLDoUnARsre0z9nD8SukuYEwOd1p8gGkPz7OHw/zaQzYRmBGXYmi8BZ+X0f3rDzMrRB9oAFT7h1oOQcH95mpfCdxI85I6AePQ8MincY5yBmpS7kO7Zlf6vCTuhHDQo8oPeDFuWGNANhNI3E/HJ4JDm+JhcF8UYy1kKN8j2EzbHsZGNcDExZ3932HDMkqP8h2uhExzer2MvAgy5TkHSg73G5ZADXTu9LL4Ley/tE6OCc6wdMKM8jk/IQo3IjXWwp1ErDxnPYeOahfIzTmAxtKvwyVQL1DR3lqIF9vsP0nqDM7/qoLblDn82vtdiOOS5o7nIfLpfsKLkDmK2k6j2HeBgdZG5yIZFP7Cv8EHIkYhkZX3nOM7XEj7vw0tJuBExV/c1dhxtKTBRJKN0LRR+LsMdi5xMbuCFdy9j72hOSxs/NhkFtp/EQs7ND76Z0C6St+1WbB66I0jz/A/+h5Bz5DTz1Fzh7oN2Nz5TuUmoh4PQ7T5MuW5mDN6rT0Okzdy+tPRoX58r70cR9M1sqiPgAbdKWkj8AD9MZD56GLqKtbHFTxo6xMg2wiGeQv4Q7pM5pvYYIul7XvXjfiZ5dsdghMLTKbi4Kfln1PJMGDJz6NdMJ7Zw7s2LsP86Xtp8II6d/PRrDB7/cu9/DCyuzPv+//u//LT/Qx1PKXcX8C/TPN4urgTcv17QUYljepsglLLw492EWN5zLn/qjY70YsiEkLfIRvc1qc2+FY/o7RbZgh3XbuKK0bsasvJUUKznxxGidg6Nl51nF4yUvIdg4e2HMtbw1mLr9Z30mHcamY3BCD63W08YbwRsLJGG9Y2t04GAQPO13gj4RPbqw5J0DK15P6RfCYaFJKJQxh0Pv9ER4y3ifeASusdmXvoHcjEhnDybigNO8dHWEol+CcIAljxQPqTWH3Bt3pUFhrOmP/Gu7kEi0qgT+13EhqoOPXWs1P8Gk9U1wXDGN0GBmA3PVNR3/Ba9O2C2wMbsTn3CvXtSDz4q7S81A36QWZJazzIteVOOBG3H2gm3IaepJnTKrA/VxhDi7QYfRhZiK8Kn1wPhO2LGXKvYLLTv+9ajnoRnilG2/0wmmJOPUhaHT1Y8AuZjdiklA/yQtdjEqDjsEDXcI9J+Fz51XzIchm2ZkzAbfeFKwvwKlOm27BQ8gvm8oxFyibOCvhC7fFee+FwKRHmZxJ0Ndi0ukp5AiTqnkFA1lDaEtgQePInxmo6pZWJMjiRjQF+cZYw3JZWedEaPWS8UMmlPBeoHsFv2zRPrrPiueVuIw9gnW9PySfwAo7xcYWqGrBmLvrMOqKfNUmDcwLc9RmhkPed1z/HsF8tww0kv7nRty/p8C6Fw7Y7bcRha8yNN6ch+HrQ6SWsPTdHYMrMLWMi12Y3Y0IspS6JQlZr+k0yMF3pQdtHeDrBUeKZFh/q9bkGSw3P/zqNXz8ypOkFBrafj9XA8mCVZ9/gmn7i9e7oCiJoM4glMvhWp6FWipXLHZw4P3E7HeIQO6Z8yHO0K6RZ8ALTlBtHAuEr4t67j6AZY1FX+Igk1KSUDqsdHkrkg3f12QGFMD9rgm9ZbAmOlawHkqdaWldhLxkTnVcnMir5OfMR6HYk9HrUpCOiqeGgCGD15jUYbJ8he0NKN5sYZUF7zwQsvgOPQxb88ehcbArxfw/f7IK8vO7EVxVbf5i8Niu0D5p2J7rHmkPVRZKZKOgRE9ubCJ8zPX8TyZU/byy2f9PqoPnx+BgoeyrGbj3s92uvzAgJLKSVwD5Mm4v4QiNXfvvu8P0m/pj/rCmt/V0OBRmEtKrhbk3WrKbIY+Ey85eWHKJupJcEPn/aFtIBXLZT8v7wPdhccbFsNs+03AAinyffjMGd1WdppyF/mRuO3+Koq7Iy1tOw5oZ2vIVqNlz8z6PGOp7OdtXR+hCKyHpAem7z0YHQGbF/bm7jiPuH96h3A9jtWZtmeH5YB9pVTjRzM13D9amF29WQ9ecSNNPUJjnZmkXHH3PrcEk7kZoFB17cQT2/3eGgh9mfxwdMIRmjoX0DyEHG4VTPFSVsWhLhxFpG0llJ7CffXi3WQezjbwtWqHtfJr8Fmy0nInhOon4v/Z7SRgyMZ+QsYG2XVVvk+GlPBKmLLibRNX1DTz/IfpLKdRdHT35AZqrWFaOQ4e2kmcHTiHPKmVmdeAWZcypYMh0xDwpEso8E9xKgBuOcSsM0ohTxQJjtn+Gdb7nhfT8YYpakN1WOeoeLCH99aMcOi5aKzTAGuOxp21wK9+y5LSsGzErUc6iCvmFj/jowt0dJo6+8MaVT1tPocmUtdVrWDZCUl8CH862hf8gEGfv1eZ/w9r1BsMF6BG/8ufgGczDAWuWS3Bl6bJ3Ety9pjH6FBreklJ/DRMkK3KY5NHfyE7S/QfZ3x1254e7dNjodODSLhW3IKhot0TXD+uJjwxUCtg3zgV4MkCL7wrDhyE1vfE1FjU34mVWQg8X/FU4RByFuru2K2yg9jWbzth/iszIpkKOa3eeP4e3qh6V98LsL0p8Q7DLfi1qAoZc7XzOrI54EpStVIXnN4QF9KCsClesKSw9IX7GDyprDDt+h48id4RSa7gRe65eWjoANyqaLdnhQuKxWwd1Uf+aD4yww4deZHqCsL5/55Q1tBkrOhANDW7/DEyCRX7My08hu3J+SaaeG/GC1pfvFTxiqh9XDMOv9RoOQO6LNUeo9PGcR58fMMC76v3bh6Gl19wNXnhRaO+PY7Cx0XLOCQootVwtgpqm0v2VsGcmV7MRNpPylHfAmKa2GZJzqFeSB2JOwWipdjLFfxY/vK0Fc2UTyJ4boZ7Sj7vmwW076cl3kDXtqNAEdLESWKMxdiM+Vr69zgynkhWHOODvja/nhGB1/62PEvBWYzPlZcie8lErBgbuflKdDNcWvCSyYGtP9PvrJth/B36LuMKTNkqZvrDg0cTtZzCBf07lM6yX8y7rhhG9+0W/w6XZ50/HIUm48qF56COUe5HdFPWwyZPNBAayy/ZHQbIBWd0k6HZIsf4pFNthciTRHPlWFRKbCa/srKR6BY/oO7WPwXaqYnYmC9Qvp6NxR2Cl2UtqfvjS844p20XU9YOlnbyQ5eSahihc/C0hbAgfX1QOCoT8byq2H0DrABm3eKj2rXI2HX4vVr2SA/OaVWq/QZd3CXEMVujHUsq6ZKHVx2QtFSjlerf+LHz16TpjNPyZ7huRBGW24yieQZOEy5e74apvtjmDNfImOilWAZI10tFoQZdtjfF78ElX9PJL2K6p6VgI09UpJyrgwZZm649we9s/mtIWfaeMGA0DLNvxK/QwNDeac1eAtUPRV67AbhuPn07whLPNRS84IT502dIe+/UJ/5ErcKuW76IzdNJaM4yHI8R39Q44sNV1muoq6lba1zIGqPx55BQb3LvvykiuA+ru9XDrYqhuXDhSBe/cfDg6Br8n7BzbewP5ZWNhwwSZyivGjsDz81W16zcx3rp2ZXInjJN7/CM1PHLYvV0cUtU69JnAy7TFZpfg7kmy79fh+8/O49H/ri8N2CfDoiDNP8+g261P7j3Q8IALxS5nzKsiRygNXNzs3MsM2U+HZM95YL8e6hJdh2IMPKVknljfIBoLcej3RybsOuQZbaNzhcev2if4QrE4XxqpO9hfCo/EETDRuvY/dWjWGKHgCKcYP9s8gnPf02dSoZG0j9sL+HdshvD0Rv6c12y6CzONXulHwHjjG+ENsM4oVmYF6omeqt/hg/Ng4qgOJZT/9OPuvB/qiYfC/g1YX/YykdzfjXgQfLdREMb/KlvRhUeMDQNMYdXwap4fpD/eK1IHWaOkY7fg2G4dBqkAN4L03I0nBKQ7HiukDg88qyrR/2funKL5P1X52m0C/tWdU6T34fKBvOMF8M0v5qoyGKMRrFkPp1tvX/4Kr84uzg1Dnqfu3lPQjIqqifuuG6HEGsd0AcYYX86wg+aCJ445wXfv2dlDAhHHJWKvo2CWuppsEtw/vo/sM3R8G/FpHdYXDBuTB0FVmXFqqPE2mIY+BOe9UMZUVri8knWUB25F8F/XhKnnv0h7wc5n6Z/uwe77TqYPYPnGu75vsFi03P4nfLFZuzYN79CzSjOGoo5/pdurBGXC9ZK04d/ux0JGcGB09Lo3fMahvBUE81dyIiJhh7hvWzEs8jphQBaGfUPchl8cmr4WfScLo6pJNVRgg2lkQkekG8H4SlqkH24mTH74CXd+8SWORKEuTMbw68DVg8EVRvD0kK++FfRV7aDITkC9WXueVgB1Ne5Jl8PZqqMZI9CawkTucCL2Pb6Ev5ow4nJb9Hn47szeo5ZQ+ojbE/1k7IfrA9LmcNRFrdcGtmaKKN2Ha2sM5yvhiaKSuY/Ql9bqfgesGxD+8SEN++ygoHcznPATYe2FdLljDofScW7Pen1YD9LwkpaZQn1VE5PL0GPa8vVz6MI+ppUPy5Ydp97DA5me5FP/vsdpf4Q1A/kwL1bBDWkuk5iLQK75Nyx7nuO85WlWTgejXuy7wAonpb4EacKsQq08L8j7V0Y/ECYPiS49gF3pvXd7X+BcyxnFOwT51fWaJmBphe3qoWw34mw/bdM5SNPAeN0CJhse2W8HN+8fLbgJxewVzntChSnzv3fh1Rs7Al9CQduaom+w7BKjyU9ouNthcxrm3OWPaMpDPd0Il+iC4WzL/QNQPM+Igzof++jcuQumMK22bykFMu4TzaqFTe94dVqgAB3XSi/cLhdWmYTedNIzi/Ddfu3HW/DpgmTwiQK8/503ds6QhHUf7R149dKN0kD4woWK9VMp+qHY/z52QWNL6VuDsMmDqZ36nRvxIVY6SA8+F/n90x+uc9tHhcOgxtnTj2DMN42I1mo3IvIlo9xXyC70c2YYqpu/ezIFqeVidZehc/tt0h01yAsGs4I9UHS36iV6GJ1zkvEwzCIRreeBTguirsfg3xfifKcgQSv7VQFq8GuEakG2eQtpQ1h11W3KEh5/9DjZHno2fNS+BVP1F7bvwPSHnHlBMNjb2CoSCpk4SXfDttbuqUHovXw6ZRzKtOTqzMP9hhwkG3DjYVI++Qc3gtyL9RINFD2YzsgMtwWr3ISgpZLCt0fw7cfDNKtQmVyomqTWjbBfkHOmglzRxtyMMM4sy0fyI+Kk8Lg4AfdW142rwdBF5feOsCJRP+IxFF09qJAGDXaPrmTD/D2yNByfcN6M8a0ThM87Gz0l4HzDQTE5yHnz+rgqPN3akKIH1YZ5DcygcvZ9KhsoaKf6JBU2/fGjmIZcerIVK7D06tYtks84T5+qE6SCTysihxkgxap1PBt8OyZ9lu+focwUYnDP6Ea5NCxNIbutBOutFgR14In+X8NGkJZqON4Krj4uYWlqRhxWh3V2wptPLoUNwJrnyxzULVincyo7JWC/rvH701CO/KazKvza13Kjrx19qD+5wCjkGj4z+gfGPrzWzNCB/uE4ebE0bKW6fVMJbiZOCOp0/Dtf7NDcggz7R3bt7kT+7fpUTQufFZZ4sUDxwzlS3FBD9un8UTjLmJl7AvJmPbeTh8uz+Zya0DKj0dQApr46IJHx7/uaLr2/YHPfUNQclOTQ116HfJYvBdS60B/ynR3Tg5Mv1tLM4I3RbHMbSPfFktkR9txl7XaHVRMDDwNg956nmvch8/DN3Y9h1Dfv2idQgcfQNxuKCkjIvIUXfh1cLYclKbzO/b2Y3xdjx8bgTYeX0zNwq2XlJ9MXnD9nqhNVYNaOKmNdSN384YAp3MvapnWlD58L0exzhlKr+p+9YNwKSUguvGTlcP4XzN5aYZzr+xfnQd1rMD4oOkrvmxuhdcpMzwyefyFAZwOLurbab8CjWo662d/+/b/K2+8nnKlJOjMD/8pUk/yFac6T1aT92C8YZ2yGhpA3etECk3BGR3Z6ET4pZ9tkGcbnobZ7FaCuvFKbJqwr5Ys5D1NllwUjoeo8yWwCTLKhf5sJN99G1X6COUtV8Rvw1S8qi10jiNt4M4798ORjCUo7WPSxsuUmPPNOJ9oT3im4bZ8Du0NfyA9A0Qo3il+wPU/r8yxsc9HwEJvEuYD9moIMlHsYtVcZ2sxcFr0OQ98Uno+BXTv2/5cClxkcf2fBxejM59x/0PeenXQSgZ/bpGRPwstf94raQ/tWadNI+G6rmjsRfprXms2ES6lvzzLO4zy3NnL4CGxiZZ7kgzuu8P53Foq7JRq4Qs84Mk4/2ODjPBsKgzOswlIg+Y9ho+cwYcSOJx/GPjEXGIGZtHNHGRbciNuZRRuHYcyWXxMv7P+Sc9IFRkrkUPjCD8Z53SFQIFItuxY+fFfosw2bhw4/El3EOGnCLknDFPItMSX4y34/qecazlshYl13YbmTybMIOE7CYNMJ3x9SVt63jvPOGqn1aciyECehCkeLxHfrwekOg89HNlF/qiie8EML90rn49CXKvfRJfii+ATH881//Uuh0zi8l/ZNeR42aVGwbMASup3icaTuRHz3FGU6XLPpH3oJ6VepPsxCk/XPStw73Ynor/sOi8DIwHOLJ2AG+T5+e5h/RsI7Dyo4Nhi8h33XLwjX/bu+tYe5lcKd6IzYs/AFnvWgaR6G2np3aRh2uxN7n3YJ6cCJWXKNUMj/8BZ3DMzd8Xs7GRYmsd1T2uNOMDesX9D554fBU8awayXTLxSuDWv6tEINmV8cOyjdCVMe4a090GTY7Ss93DDOKMyCalKakXmwY2zt2nuYXnDpxg4qd2LXmfHTPFAmdfjQMfindXj5JJQ/aXHkNrw/IxGRDwU7/OzLYFBQp3I9tDnum2GyD88Lq/e9BCuK6Swc4BTz+YgX/+5TZ1eOwsW/Z5Kn4ZeS7x6rcGFrr4IarTuh//cphz6kbFQkNYePzdd870JC2d+nE7YmLj8lpXMnUh227u2Fhw/stWGCs7H3VW7Ao3HdvO5Q05FzdwDUYXMdD4cHK38JfIQB++OzyOlx33qRUgqevbzlfAE+DFJKyIQ+2t1rg3CP8tK3cXiYgaV8HlaWKKdswDbu87QtTO6EH4nYYi9kLaTvHYK6g51K9AfwPvoyhYrwkY5FnDZ04gz0NII29KW7xA66EySGthPSUMCZpUUJvjHmMb8OvYOfTMVAR/mQthR4uNv17XNoS3uMTpbZnTgj5rWsDDmFWvrOwrq6yrP+kOHN492FMHqL/08FPMdT0/4R7uA2H/c45E6QOV5qvgufxdzMj4DmGtK0TfADsRlAzuJOUNw6f4UG8vkVajNDkTf2r8/Bn/nzMRYw+YGvhx2840Rekwul9LzbfsENVouiOUhZo5C0Dm8MMIhzsuK96g8cEobqIf/tkIJW3JnedvDPvfqDj2FQDs32E1iWa/EzG9JbfMtnP+xONHu4xAvCS04HfCXgkrjRuCNcbyZcc+GFUWGLYvij+z+lavj6Q9pFB3Z3Yuh4g7obnPGdP+4PLRxuviyHansLP5NxYN2ekikTsFvqqYg65M/SYD4HiT3/VXnCwemfByvgbMhS6C5O/J0d1e39UIaL98Ih2FquqsYFySUcjx+FIyHJh0/A62VtFPIwe4p2XgMm9Z3tN/j3989i6y/AQp0fb67AsZ5jic7wu3TQvTuQTfwB82u4ceRy6zxUiMq9LcXlTrzVdrc8A7V/q2towANWHJIG8OD3iyL1PO4Ey548ljboSbdrdx88keITxciL+a3If6QPqdjPBZhDXev1G7aw9derpC7Y8SwpZBC+VnroMg6fmFWTcfFhna5lPTOAj0OHoi/AQyHsfldggZP51RB+xFWZlnE0ZB5TUEmG7sP2f1rg7Iq9P6WAO8H0MsuRAbLJTViwwaQE9eQwmPCuMywWvn1v5ZEKk8O+ijfAlpjRyzNQ5WzXloCgO/F8wPa4LTQ2ceK4CcNL/Gk9odpq3I57MGD7JNN+IXfisttz8kOQuZN1iROGks76XYHidjVHEqCMTABNJjSaV9vOhWGhTDPFUI7X5IyIqDvhldt+/CScO6DDowC5ww+N3ILk15rcaqGCHr3ADjGsU8yuw5SQs2ybhgHeszzp7wcvEO63wyANeaVdLEx4RWmWCslkzXReQL03BfIFMGQ3rWQ5zFW6xd8AP9gOsLbDNgfN/d/gF5PqnT/hD0GZlWn4J+/DxCok1VIfJD3uTvA097TvheZiV+qYYLYXSel/kCEnNUcAplQpPBGHmu/+RJ/+9/345CBVeNRc31MPus4eSy2Ex/cMlM7Bv1ufvDnFMV73nc7CsOsrYSsFn3jJJ1VIYp0lyaM+wse9zUEdcNuf1oBMCnVVaY1DEpZ17GQm4IgyPY06POVgGNgNOR0qvb7DiwbCzr+hkN1LBZYTqG/vRdgU4FzOFwYtSBYYRGUIXzdyLYedxDonP/wTC7mMSX+mQhITsg8N8Ma7G2kzUOYJU/xfaOLw4eHOU+6EKp2XrQTM1tO8IAfveHIYqsEfYy+OekKv+s3lKpjTJP9xA5pKhVTtksb+Gt5dsh96Zb9ZpZf5V/eS5g5DDruICV5Y4ldYZQ2THUJSYuG54zWPU2HC0I7IF/D3RzVpQVl3YuD0N3EJ+CzF6agcvEFQMdrCrV/cy3GQ7urqTDoU+tL2Owd+u0371E0e8/S5Ic0fTlLfTQmHbyVCIyrgzXw+rzV4jlLInUzBnajVlnChhvU+is4H4YVkY0cOGJ1167oQtE2JtZeEP/zKbAlIyuAloQM7216JGcPzHr9ErGHkfh7h6zAk2l7AFZ7ZWcjrB+2pZw+UQz1JMfEF6JvbKLoJ39DailAouhPjVpTCtLAg7GMhkyriM6yr8D846zFWKAAD3rQU2cC1r/LlGZD1T1p5Lrw9s6uiGN66Yzh2Qx11JLXhlzuceSP7OwA+a/aer4TKh5t3cmmgP/isTWMJb7sHMEfBjwoyHO/ghKUjVy1865DN0wIDg7jjnbTciU26C0lecOpBSmogNNoaSX8ITbTiCmqgNB9f3SIUW331cQsOlkp/3q2NeU/4HDeo606UijxLGYd1Jfcy52GNpVzZIT13YprauksevuVz69OEEpLRP85DlRrn7WAYEphPHg2zTq9QJcN9z5S462AwY9yFI/roS2x/H7OBBVwvpRzhuR6n0x5QzotQugv3VgbeboLUjil05OfciR7nSmYaKHht7D9m+NxyULrfEPlloqI0BhfUi7RnYQxnc5CQEa6/xOZcga9f9HZGwp1/Xw4kQkq5wF9PoeehTLlhE/QHl76oT0GRZ3Tnl+G773oXd5hin6CNv0YJtU79dGWAFqZSAWywq7CVxgTW/1g9mAabI1O4XsLlU+rHCqFq/7p0JTxAsfST28qdGE70WBKBQ4K7yE/B5LfM+teg+nxTWgr8qB2X9xwWPLtanQ9p1xTby+CYKtdQPZQ3HPhvBn4vJnlhYY3fvV4k9QgWLfwI+Qh/h+2MYbiEfNN4lckG7SguFPLBolzlRMar2O8HWN4cgdn7Vmr54eP/4uRt4IGfDbTRUJZmkicZyg0sPmyF3v2idPuvuRMNO5N5D8EFAWpZLmj/wDSRzxnx07z9Vgz6UWe3yMCB4w8kLsMH+2aLHkNGx562NLi3p2bi5b/rnNqzXS6IR5u4a4NwhtspeBymGTCu7ndFPtVq252EankWdxWgXcatJ1rw5ufsZyweyE8rp1pu+H5bblgEvnZKcbWCWtfSZ0LhNY2cfbFQSbRMMBUObiWdeeaJ+pimY/kG0mvs9nkHe0/xrg3D7yfXYxi9kH/CswVHYDPvZAc/fKYUYDTmh7xWm/GYhQ8MLyavQZnly7yc/ogX5btdBjDjvdjKBSgh/YvZHh68Il42AituSn3/A2nvEaSr0DXwY55AgDsR1TlkZQ4fmAsH2sLb894vbsLEC1fLVKKQZ8xJ47qwc7SDwQzS/5Gbj4DUiw0bn2BrnAp/D2zUaTb4AbcPGvtPQNfFiVeL8NzZIxG80VjXU3bsAVAnJpO0CA7/eC1SBVmJarMmaGwb3MQWj/xRb1njg5LyhwSPQ5KVwClT+MV3QS4DFmnzHe+J/1dfv1n/gOWCsTET8FsEx52zCTi3LbO9MoEct9i/X4IPFO0y7kNuLxaHt/BZxbnUin+fH4hp+wifZrpc+gVlDVpi5+AvFqGGdbhTzaziaCL+/rzw8HUYz9tF7wYXqf2U/GFf6/V4/TTsE+cTWswh9/LnnXbwUJ2XwlP4MjxT+ws0N/3v7vC/7ymkl05Bgfml2qF0vIfJ/vVJ+N/AMdFl2P57Zs+RDMzLC+0RFTjP+IxZD9Ik7TxrBhsedngWPcP67ZR6WwWpItOmmqDMYHDLAlwX3nzDmoX+vijlNw9cMFbmEIW7GTm3tV9gHyxiOGkMz93e62wNl36cjn0Es4r05zvhYHuM0CA8Q9lvMw5Hf8+dPJWN8yy/4y1FOBi4+Eob9tGOdfpBIoHyRiOctf4auwEnuz617XqJemddS0ULq8rVhhTy0Mfpbx7Rhnx7ii2MYOlmZG8s3A421+2EPBM2Dweg+jWX1l9Qh+vNh7B8zGcf785H8GzeU/knsPari28n7EwJ8NmAxrWnK3cVIB+pdmzvh+bNDA5nS7A/UuzIM4FfL88tXILiqovb9+G5ziidauifWB31Cf4NWu7uhgEFZ7fOlqIfde8+Ywq5Llneuwxl2Jx746BCJK/AZ6hNs3y9B3LnN+X9gJ/dny5NQGWbwJNLcCRYRY3tHcbLddNYBbbk877ygDU9d3e+gln+fSolsFZfMrwG/nfk8lXK9zh/H5p/zQCDpO8tskFjCRoKVTgUw3PoJmShmLPwhBMp1Rn3ICWtDvmzctSB/Ksab+Bjj4jId1AiK272z7/7j1zPslcgL3cPPhKE62nqAxIwaXOASqEa9cSX65wWNBa6mWQIeUc1d4XBx1OXSj/ChTvrJJ1wQipOfQC+YK/YsKpBXjLlKV2HMcezI1xhldDoejaUba6+Mggbc7fyx+Ht4jMb81B1IlRpEyop90VQfMA8tEqpKMG7mbnXHWB8PVHsBhno+nYEQPZbCa8NGzFe/pKNi3Df3n61a3BL+4V3LGSScHxbAWmefSJphM4Kwjqd0GHT7VZiB+rIVa6Gp/DWnh7mN7BjPbt4BD6tPrZzX6c7IbpNryMJMzcdLDzgQkxjcBkMNePor4fnDfxE2iFrUQ2Z4lf0G0HXTLUhZzhrvhG0e/3bOhxSSl5nqoJvXS5eb4K3J01ruyBP0mPd5T53YnVb6cWOb6h/cWs7qGD+i8Hi0/CXhsmRIBgmxPjlHbztdfJYHbxKcim4FW5P3vupOITznf4moQPd5j2SjCGrnqbNfagxNRH+CZ7lLxjvhuopfoo//l2Hrl0QHXcnXM4kVErDjOPEEWW4V4Mp5Qbs6JK7kwEvMHEN5ELBaGrZEphJcpRN7jfGVX7DWw0WFhYP6kMXyjtVQfDhjtn09/BBsNfOenhOk+ZSG5x7kPnq4gT6hJ4YmmvQwjjM0QUmlWcspsJybT73Rsg2c76vEzZ8CpMehGWj9UnjkOTU7q35f3//SefCJmy9njPKM4n1qHC1PwtdHVc+mcC7FneEL8OrtzoLIv4Z6cYYD2knOV0z4LuTfRd6oX7K7+W/MMSw04hsCs/V+vCOGkZ6Vm6cnEcdK7a3UoRM4qwftaHQbKewMcwz/ShwH66t8//sh86rYhq//n1PQj5vDk7kGR7YgCEcycOKC+jDEmOH3aCL2YZqAJw3v/L6Pvw2xzIlsoq+3d7I4BR8wpNYoQhN8katHeCFi1V74mC8i7RzOqxuKevPgV5Ma/5bazhXvBv7s3vdnahM+2pEDxl5lm+owKCVwiBPeK+N6slrGG4uZvXn3+dcr5tXIJ+I2EnSDfRn1BllfKQeBOub74LH4WYcR6IszL3w+F4idFZhrpuBAdLN4mvQxzUok2ynB3F1XYWBBm6eOhptBc+o8O68DrMSeZxdobWXX8ZL+Kq5Mvk3JO5RUi9CyXum3luwdMrQI5YCz7X5MpUK3QQuXMiG7pkVfguQ3+6/KYXdHsStdqoL2vDMvc12IxgVsKRoDXtcBe6IU2GcFN/mTkOHkUgbNeiqdIEzGB7v4vDqhAtfROcG4AS/is04/EttOvBnrwcRycWgvwrHAzs/ku7zIHalVJJowm7HAudw+JHi0+9HsGFy/EIa7GXd1/MSyv5NMDlF60HULf3uUITsZ+Q0dKBCQKeQOzxNfevUE7h4hLQgG+b7PhIshEty6vUqdHg/RVk5PWgYJ1liBnvooiMSoVi4HR0rvQfxc6rNWxr2Pn2u8QDeU/TJ+QDtKLei/8Bndy5q/MeAcQQ71gnA/SP35CRgSoSTQOIB/E5AwrOnUPLTR4438Pgx670z/9xPmi5y0IM45e/PdgreUt6TqAjHzB4d0IEKcsbH1lk9COnG8tfkh7E+WXwi+2FVy1EhHaiSZ57gBx8FMRwKh7n57fGPoL6DHJsiB55zvPuJNnx49ianMQzjSD0eBz84Mhp8hXbrO7+MQPuBVZNp2Mq0OLAKdQykrwtzehBeQVzN1+HBb1fPukHjwNJOfzjn5sQYw+tBJNedSkyB81f3sL+AK7k2iuOw6/xgICefBxETvr33KFRm5Y0+Aem+3h1TFsA8Ocxe14XWFlZLpnDRJZojEVoo/rHogF3uL8f6YRClo8Mv6LV8ankOSjdfcz8r5kGU8OeRm8KDP9cjL8Phw+06CbCoP6TxM2TJPXS+F6b25w0PwccqycdOnvIgeGSzqxXgzdhyPW1YX11ceh/uaJ+rGoXvFy/pzcC7noMjf2FshfY1OXkPwmz7OKk6bHh2JO4c1HJRzE+BcWOZOwYhk/DEo3EY2CchvACf9q+pySp4EEY17j9UoADNtosePKR+rt0Lpk35C2VBj74zH/LgMxEKkzIYqepLIaOOdbY8la4Mr46syejCzTyywYfwjN30aB1cXVDXnYWsA4bG3BoeRAV76qIING2fenAK/p0kBJVg4s3Eeh1YX6Qk7gGflpqffg2THFa/lsKOiPjbtXDqWBKbip4HQeUrXqEL02Q7zc2gzFUtr0joe9kvsR6GjNhIt0OVNr1v36DuwtqPPn38blGQ30+YNn6IYxb6UD7PPHTOg6g+Q86nBGktOj7qwLbfT6+YQOdq8xTCxIMgs2iS14Dz12R/GUBdfteaWLgnaPhvE/yzkJ7SDR07ryj8gIncUuMT8OYE5f0laO4ZUSdgirjKEdi+AJMuKGXaw/2BNmq34a0jEdM+0FLKsULWyoM4SvPWVhXKm2/t14e+HR0XgqGpse32PKRtEzrLZ+1BZPRs/RWDM/q9GbJw873TkhOkJnVKvQO3KlzVgmGrYetcPmy6Kas0Du92BczMw/Ov2uI34bQPj4iavQdxbFN9QB++WLwdZgF54q0UQ+CgvLLbFjwTc/7b6aseRCHt/lA1+GVP24lz8NZf43F5Jw+C9JBBohbMLzmvbQQ7Jaua70OD9Q6tD/+ud7GStMCPXH4tq7DMi55a2NmDODAodNIdtp4dnQqAhHz6kwjomG9zLh4y2JZy1kJBeo+sv3DZ1ceU7Bbq84/17yfhJa0XbDbwy/OZDkfoGSAT5Amroyqiiz0wL319GjXQ/+nmzmbY+7BS8oQn6pyoAqsrFKF/s5UGU661XG6Bk8vRbF8hFZll7whcwsEmzh/5bJtomgEztIIOvoJlpe7dJVBeKU/hL6yX15qSD/Agmr9zprrB00pRZgFQSZTiUAR8SV0mR3bXA+dyn01qSEWj9p4Z3rfKy1eEd0gasm/ApoBPdh6Q734Pzz1YcOHeoGQw6vub7pQzkDxM6IIm1Owi2P2h0c4Azlw4KsUyWgzjlkoza2BkTcr9s6EeROikhI4p9Ejp3G8DvTloEp9BOWrzh7PQvniPlGwY4rTq2F8VWKZv8V4P5u7buhUfhXo8lyKdCW9bK5O+hhzFZdkzcE2Ta1gpGr8bKX42ACa/vnwgAn41TR6MgyQHbod+haYv+nRH4cUmZeYZeMCj9Mdf+EHJuF4kxoOIOHsxzxmK5nO4e8NP6RNECFy8SpKbkOBBnBDzc3sKPUMpFN/AU4+L98xBKfqeNtFE1OPevCQZ2C4cY6cC4xN+6Weno+406nAVwsT7FYuV8Ivne8lJ2NTl7Mae4UGE9/GFG0KtnGH5OKj64Rt9Bnzr+G00F37LjEz6C2N31V8ny/QgZrd2yNHAPzmhBkqwZzD2oge8p8t8/B5kMs0gewg7vPMVI7NRL7ImmZPgqr3gzDPImCI+8wu+C7qZy//Sg9A+TBEgDmm1MozkYPlKGW1KPsbbPjD5HJqqkdcXwHj9n0e/Q5XyOCfGAuTZRVKt/2BfuhOvIPQ9RnHtInwdfPdMCRyh4skdgeY39gVPQ9Ob61Z/4fr1tdlXJcgD7ZaWUvin9XlOLWStO0u6DotCSoxES7GvLn+TlIHUZLsYVaBP7OKv9HceROOtv/W58M8S2bMSqLKaRjLzTws6C+73HoRit43sMWg+Xc0qDf8+DZ/cXYF6a5b5mR52F9XkssFiObKlC1DYj8TsEYwNuiGbBttER9lyoDf72uvQGuQFeUd0LLz84I3rE0gpep3iM5xeZIlbgY36kl6kH5CPRoaW+6BKg656yWfM4ydL8Q9wr6cLWwvk+0nT8BeaU94xOdbsQWjYditKQ60b4iLKUNBeq8G/BX1G8K38+9BKLz05DtIfS1Kvhad/Cq/OwJbSxyNr8Oyp3a3krcjrxznve9qRL6r9z4dgfBbdoykY/jLwBGcH4oI995sxZF0SarwEjV0Kim7A1S0WyTLIP93L2QBFwxJoOyB306+Pm1D6xBtf/k7UyflXDuLQ0vStmRw8akct8hea0YYfJutCfbfbv5cGBsZdqj8Fq+OTHG/C/z5YX/CCRxNFtYPg10Y9i64h7Nfxagbf4SqbiuYEJFf35WMaxu9/59ttBAePOW5bQb4TFcvX4a14+hLmUQ+Cl97hDRc0Vmh9LgKPWWR43oSbbaTiFfDKVrVQI3w2HMTdBYvC1oJHfiMvyX7cnYZXJD/7/oUTMlWO3BO4/5Xroi7kpp3VvQNjZDbk3kJtz4sylbDbuflEE9S4GXhbYAH1S/WQqwTsHHjrRkC7STY/VzjtJRf6Cs7LcoWXQrlymoha2JBUmC62iPGoT2bKQrpi3ixVyLrjfb4P3NEvUlkEe9yLqquhR49C7Weo7WxG6ruKfnZNnCIMTpxh2PsIXl3o5mqGn+rSTv6FqbG1p8n+Ik54phVoIOfj9wxXSD0JetesI7dgDmuCgA+0mS67WAQNyhozVyFDL5ne0Z2ehMYTe/OT8IFIr50ilAkUqUuCy3u/tmX90zikPx/WuVsemIBybKkTwmSexNGSJ8snYPbBF6SKsDWB9LMjpScxFf7tmyd8r/p+MhDO1PlIV8Aqga2wJZgaxZe0g8qTcK41zqGC3Ffs0/OgqOzugjIY9S3nQwMslQnYtQibyJjV/9vrSeytXjMRhF9VRq5KwhF589UftJ7Em5X6vVNwwl2KfQUq0bQFHaXzJJ6+Z565DKnou3fehOwnHh/0gjMClsJBsHC7wbcAZiTTdn+H3Z8PTEzAlUau7SW4HXvbT5TFk1BteJwoA980VRWqQBGhxRM+sNN6tKwITt8w6q2G9tqdc5+hQxR5ZwyrJ3GCjnQ6FXZeIt/zEraaeT0chldejR48dNiTsKU9Ls4N3VWCdY7BffEut36wexLmom+jJiFv6uqbZUijUqh6lAPzzsI1dBl+KCrYdoRkfOpsXpDyxi+ZIPglLMw0CloYW/ZUwFP3X+hOwoMiYY7LcOWZ8wMSTk9icNHq1V4YSu6ipggr7xdwRsG2YZu0CnjPvqmqEWZ9FP/RBeUGzp85KYh1K9a/rAhFrhmG6MDm2mxmLxjw7URpARQ/4DdQAfWF20ia4Lwy/40gIU8ipWwhOgpy7asrSYYXfso8+gF1jA0uHxRGXPxxC+WE+uYZr49CMUu59WFRT8I4zYBzGu6rctL4C58bXGUQFfMkcoNDd92CVVRrR33gi2uOhqGQLsiWSvW4J/HjrrG4Ppy11DO3gKMFsQKPYHWoZ2sNTGIqXW2GK76b7F/hQlnPG34pT2LneaF+cajZGkxBwN69insDYOeMKF09XG3+JdsO08Mzr/TDU0013wqkPQnZ2ZE9lbBmlepEE3RYnJ1dhkwHz2ZzyuB7B4u+HIWH1jkoTsEXmwOawVBixc8zGr7pFMpOgd8dJqJ74OTbp7nMspgPyYx+LriQkEV1DJ7WVbvkqIB4uXb0sSdkdzjUFPjv+jbNowLokPvU6gecaWyNnYRMzTsal6HE9vb34yrIry5JRjl4N/KWujocGtpv4A9/y/pavoOmq3se1UG7xIRPbZB7QrjjgDrypEtoDyekeyFGHIXJ/sX6NvC6xTm7FLiLeJb6Ar6h2u55CyPZO/7j1/tXB5rMxCH/WGOcHHSJPVrnCueD9hdlQnVhg/nX8EPVk6Pv4cXZkSfl+p7E24HugY+wtLTlUBdkv7NCTXIO8bBvZudRGKnNc+YkLPC+5K0IywYcmeZNkA+DXYabMLNNLn63KfKGXjRVAjaf7XxmBSMavcavw0FxYQF3KE9ySZvb2ZO4NPwu5Rg8VnNwRhraivccuwLzdDM+pMHbrmNZP6FNN6evxi1PQrm6ptYNrgRMMt6FW0ostg/gHmHKHT/dPIl61hn9WchM/S1rHeZ/WUqVc0cdcpTbcwuKu/iY+0A57/q8UMij0ZUy6OFJ1MYtLvyGG+MsaktwNU1tQdgTcdM9cdcPEmrX+8KhXtWySBxklQys0/D2JFwjalgNoeAk+S0rOBJi3P4ANvwYCPwIj9rbDnb+c3VF4js0pORt/OXvSXSlynIuQHIZ0ztbUO6VESEVgPnsup17GzJ9+EXhB6+XWFqFw54pHt46qOlh8Wn/XdSDz2I8rPAMD7UfL7wbV6z/LdSTOKJblT8GAxjaaOfhRlDwH4EwxNmLmTw3eHtWn/YuZJCvdHwA2ceWmmejsI+8WRPdgAdDdz2iiMY83/PikYDZAnQ7LkGpMPNLN+DPtdcfPeD/FNtnPFZtHAfwMssmRfaOSMqqKCfKjKIiSVaI7FH2HiUrKyOjlCcRshWyNxmZIURWJEpJ9Px69f1c5z7uc85/Xed+YeFpz49H8JI2cfU5/ENTWl0EZweP8r+FTxhNP9HFeRIynKSqOvBYzVSuIexzamW0gnccHtbmpHgSO/XIRcvg/AWPuDooc319qxM+UHa+w/TIkxj5svJEF+r/aqExhdEsz2/bQuJr55vRQjwHf4bkHDx82z1nDX7YFLzPW4TrRGneOg89tiw+XYVPwkINLOCNr3sa7sLu3xfk4+CoYHxxOqyhW4rvhG7U3+5sQtFLrisUxeiDyh1WTLDw5J/zS2XY/3rW2n7BqdDVs2TlmBNFUkePwtq7ftzGsNXhbfItuOxBvu8OPHtM74JaPfZjkeu9l+CSos0lY1ixl+tjEizmtDhRAcNTiysboOFZKoVu2DnWvd3djP3g24vAUXjhcPiuObi1z1roUAu+dye7oysUu6G/7gc9vqV5hsOqoqXcb63Yv5JZJbfgmxz1il1t6Jf7BVcUoZ7xvjp7OMkXreoJBxgY34XAWUvDHYc7PYmWl+F3T0B/nnoGZdjum6F4HybaPUxthMe3+IV64HZ5Wd4o/GSTXrDeg/nR2CxH0os61/zZRAuXzm6tyUEXbh9ea8iks5zrCuWKzY/5wx9np+vD4RlK6/OJ0D7RaXcvbH0u00Dd50mw3KG+wALPuM5+4IOXMtssxaHWzpK147DnShb/TUjH6zrxGDoZ/WfzEpJ2Tfwqh9+L8/s/DqLudofcWISDUWZr61BWkL9aYghzdPb+7+tQwPLVPWuovn+c9Ta0u6BJOzeMPkiwTF2DovT3Dv2FTOu6dodGcB3ehnwDqGYtRFjC5s9R3U4w4QPDTmIM/SFPxGpA/b7bgnpw1+kku2A4xhpUXgSfRm6qv4Udxz3G2mDTRyvy+E84LnU/JQN+rS06kgt9+hZ4PkPaiAxGnmnk4y7rc1GYVfnwlCxM/LT2X8OqJ6EtHqHSDS9VHJr9APsV7z3jXcM+ImbYaABrKi+ZW8JXERfJnWH2ppfRh9/4Hls+slnIJ/Du+Sp0ymmT493EfDCWdjGAgo0H91vCeLsD1U7wmyXT7Dt41PtC+AfoMBh/ZBaqZBna8P7xJGy4/gpowX7RiDZ96O3D52AOOagIam1SL0JuQLzkGjy1KGB0Ex5S49vtAk3MAwzyYHQn54QAmRf6yOvUJfgzlXreCCb8eRx7C/79a65aR+VFxNptrHfCeZG4Z8OwT4eSnpnai7i7uddFHw5o7+I3h1I/dvY6wBczJP5esGD0cUodTHj3k3IL7jC6ULaLxovokSuwYIb0Fiz7eGD1WHCjKHxbzS5pAQN5ax9nwKJlX+1cmL5beWc5VNwTo93O5EVklYiSD8Kt5x3lU1A5IymUcY8XEWz0UMgeTpVI76mFy153EzdhjtHEOUpmL2IjVmHnHmjybY/1QRjCdo9LBl6KJ+87DbNeEc8coMtvVbd0qHaZ8lAOJCPpnCyFhmOjTLVsXsTFRYf2DmimRRM0BHfIBXLvYfcingyku2jCK5/uH9KHDmd9P9+AggIJbbEw+EheYDq0jeuUz4F3n93W3ILXRIzztTi8COqYpZtXYeaFAD4LKDrgxfyU34to5Hncmw85Gjui30DSLRsKEgEvYo/eflc1KB3+VPIytGaXXTWG60s1hhQHvQiDoU/cTLCPm26KE36Z2LF4Dl559rE0FH6MvugeC6uHu+TSYca0TWAdZMkkV+6CJG+f7RqBDf32e3aLIv/O6ZNKsFL23tPzUE3fw9IApiTQ+FXAajJCqREOd3tQ9MDM8/SD1GJehPnEGRsduLR36PB1WJXttGYFlW9uudUd9SLs9iURXVBeSH7XCCx++PndDBy3Tnz4Db5N1zbagkYyTAd2S6JexUeWmeHy3exSHrhYTbVHDFaPzo3IQl1GsZyXMCTGnJdVyos4+veKkgqMzjkhHQAF55e3IqDGvRdNSZA83DbqGSS5OfpCSwl52TPkdRUaiXzQsoCR2TM8TtCxa/tjA2S6ytZCfcaLcBZmYJKDXIvTh2/D4b9JJAHQ31e3PwLKbO3Q+6ntRWzSSRwl1UEeYyxo6WHP+8+X1eGPxMPpwfA+WbnHA+g4paKbCt3bn9HvuuhFvOP1W9wDyxdMmrlhR+SJPQaw/XJXdyPstHyyRXPJi/B4xDPCCpXOZJUKwOmf/ZuKgfgeNcp1LbjnALFyFZ7aZz8cBqt4lwYb4bqbY28P9Li21TEGL8RwLAyG4Xvq985/gopB++a+wpDRiinZ+4gbz71GF/gwc7rBD94sU2kIhzosdb3zMV7EQe+egR/w4p25kZ2xXkQbdefXk3C8/2aYGzxypC8yCPLyno2NhnaUzuM3C7EetFh3gZ81TOn8oVYEa1k/3FUhyytW5EUMjT47fgzyZLHrnIEpcfk5S3CDKbFhA8rI3h0jL/YiLF+2OmtBC2pvsgSontbN+eTf8UFR2Tz4VW1Lzfc18tZGa3kf6n0XDHoIDYsY972Huj9cizneeBFvGBd6hOHAoPlXKZirMk9zGrq+T6u+B2N/tz38CDVLKkoWIR9bQd9P+CBZ//fBeszRvhkOWXj9jbuCEuy8sNf0PFSxj6EPh6+Kjue9h47OR3omYMSkxPcvUFXR0JCxAfmy9vTjhAbE40wR2GcdLHEVMr06Ux0GR17kTybA6xf5yDOhnnf0Tbl2PG++bLQKDI/9XHYR2no1+ETDc3ONdsNQ7WBPwgz8wjVd/Q1ePp7n7tfrRfgJrDwLh+ONx3sT/2n1MrAVcjFGi/6GDuzcVyj6vIhjoyVBTFA/hCftKTSMYG8vgEc0uH5Vwg9vhQVbYUZ1NwXFey8iyT9kwBeKvP/wuhKqad2da4HvfOX39cODCul/REaRr/wdh2Xgzg9WJoowomDR0BdqMpPceQPLtGqym2H3mZDRPvhgK7RXcRJz4LzgrvOQ1rjtpAGMNNDwewqtnrk8X4bORj7jv+H3wShmyilIl62+B7YLiNZXf8L5Mga/22AtZeyRQSiny6XMPI16P6cmowtP6g/YmsJiwVvP7KB5c2yZxQLqomZj1QmqeluK+0LTuUexLdA+eKP3yCLmpefhv3ZQ8CQh5wlZ667cCYXakndPWX37F/cbPq6Qh0K12h9GbwlUF8KbLaXbX6HR1blTf6B5Ea/vrlUvwnsgsO42DPpJRRoIpz4mKUXBatbhkA6488intt1rXkRvTjP1PnhuuegcH3T69V+EONRoy+w6AeU+TvTegq77JwcfweZvfPuzIUOMzdUSGF5iLeH8C/FYq3bxhcF/2Cruw5Ldw22VcPFkfugS/GSh3bEBc69uMlBseBHcdB4zVr/x/L20orehoWm2QwCsSzAPLYJV1sPTK/D0St3BLfjydLHD7s1/czy7kobUm6CprqDcD1M4e3UEIdlbTFBYq1uSGwondjP/ioVBER5KGbBkci4yF3pQGI2Uw5HNUcFGmL2jJZ2EzJuwyuVgJyB38orFOVh9paPwChTPtd9q3eNNtLoIXhyAefs+PZ+C5ezCO5iZvYnQQQt2VSjHdcvxEvQ+dafZGAYwL5PxsnsT5jRaRofgvcmSiuOQY1fbUCDkuaH1oRpqJzPLtMP9eVPRg9A3vXzxE2x/1fDlJp83cUynVcMVDvX1v/CHHVm6B4rgyrrh02nodeMV6TfoWURjtgUjq1smxPm9iROuGoQc9KcdSFeBO4mdPsGwwuOMYT280yRY9Q7yfqfjHIVVblYjiqLehEkzo8J5SPqnNtMATrf1yETAjIsVL2rgufQC+k4o05PvMgwDm6KsDkp6EywfiT4Z+HVyQ14JWj/8zJsM+0bdq6cgV+Fj4a+Q0aknZhMWc+zeopRCPko47BjlECed4VFO+HEsVeMgdItZdL0JrYxPH02GE6cuP86C4jSODEVQypet5JKSN3FmJ6eICTS6fSDVFtps907mwNvyswcWYJ2A2qN1aL2jiIH0jDfxoGJpluyiN7Fb5Yc5I9zTTTbNCX1bYkbPw9SzKu0RcCgzSy0Zrm7RtmTBl5okZi1m3sR38rrF9/Bb3T2XSageP5EtdsOb+I9RZi0I3txj5/UAnmXLI0+DR57WD4bc8iZCou+Yx8L2YMm1dNhW7HywF67E3Dcls/EmPgxHrTDA3yKPfDjhxzvNxePOyPf7XpVFeFzh88hP+GaEVEvJxZuwz1U5EwKXXr8ZjIFnBmVvpUOSYq428iBvQvqvnyUTrDJeJOOG2z6lF+/AJvWvFwshU0/dt+p/2qVFtcNu3oBDQ5ArKyErJAL1WLlHPRZmLCUupcOu5m3PXvhSfzGPMRLfn1GrwwUfkmSsH4QSc4u76mO8iVtbDfnvIPORLN1R6DH7kBCO9SYcEuy22iGtSY4oaxziVmLUJwBfCnN4HoGKbyb4TkGeN0JMYdDHVsPkA1x96L57Dv6czH/1HZ46ltI4mOxNXN7z2HEaqjLmc36D1lMvhU6meBOCGsKvgqDBlkNlN1w4rLOX45E3QZcmWicMaw/T2kvD5vbKl+ap3sS1j1YGTlCWhXu3LyRP/Nk6CAvXSMwl0ryJUa2je07C111WtWrwx+mrUh1PvAllS9+ZIfi+KDdhBlaXW1YfyfQmxPSZzX3g5aycffchF7tGy0OoXTpFDMI8E+MAtaeIR7tbfjz0mqQPa4EFJz3l++GxuuXlSejs8iSA/bk3cTpFQlYYyn5pWpSCc6q/DvjDD/TGu0fg6qub1Z9hqo+78xocHR+xuJuD+nzyiDMeMsVavH8MzYd7LSbh/PhhGeZcb4LynsYSD/Qxsn96CDafV1Vze4k5Oq66MxgaJmlXPID2hUeoxmHUClfHwTxc/9eDIFlYI0578gycEE/XbSv0JjolqZkGYdNN385PUChp+qhEkTfhqrzuYQ/5qztkvOAxi5zVu7Crxr5apBx9m33BWwauNRyXV4Jb5xR/BsDv4aybfbCb7sbrCUjdUOa+BEfDjmbytXsTAgvKdofhXIjZcXkoSVT+uQt5420YGuDI3i8fuuGt987/jcFD4xfPcPV5E6VU0cyiUNj9/bQsvO/O0RwE3x4I39ULY77JDY/Dwq217EUYZadHK//Bm0h83TWlCqk0tcovQye9dLp7MFnH4Ugl/GV0grIVUhTTjPVDnv69rvSfsE/pJ53ngBUHBA+KQFp+NvXbUP1brEc3NBqOvTwG02geSSzAZbldVNrTkNlgxhAaHy+tsYanr/3enQPPy1OudEHS3S/bP0AnXoP/5mCdnJIoyyKea2SdSgDWNRcuSECbkRYRn3/rtQssXfDFvNvPEXjocPbgLPz4qVo3a9Ub73M6ckUwrHyJuwbqaOQXrsFxm+5fvGuo85XSMXEYbFOsaw9/vvpqXg8pBU5odEOOhXCJMXjHSWNzHbZJlU2QfvcmCA3RJgZo8zrmwHV4z8DtwAt4/vUV2jKYYnt6rR7GWV2iEt1EPavc/C4Lb/sEjZ+B99tUQ93gBWZN9go4UFVJ3gS730qt9MK/H4oojpL6EDkjP3+cgt+lz8xowKHTrU984QtpPvrvMGuHuJ0rmQ8xPvdHPPufDpLcpVBT14m+Hg6cSjfaS+1DOJBsXeSDdAfMVA9D/ciPdA7wdO+D4kHIec/HSZDGh1hTCbc8Ci1uPrmm8G/9Io30MZMPcYxz/M9LWPpdcP01JNMO7tq1x4cQTrTPU4PREhzPdWGMeM9jM2gbxhcVBvdxb9x9CD33DwU8he7fC27MQJbUDBUhZtzXrw+nJeFYBbc8AZ3terzl2XwIctstTzXI1H/EQxfa0pQ6PoSBAaE3aNhxXJrrmiWkqDfSew7TL9/RLYE+Og8v10GyxLZv0nw+xMhjnh+KMGO/76/z8PEZTYogqOOuzdoIPdL5RSn4fYhXShznPWESmctEHmSOrJ5+A3VCGOdb4EfXCc2Ig4iLVZpuMrz77obRf7BZsDqVRNSHeO9l9cYUOqfmNdhDviN/Or3g5CGTg+lHfYjlU3rHcuH+5svKFZDn7XYypaQP0dtZ9Pg6DCrSX0iH2qwbv3Lhu+8ZlK/hL2Yqwfew8Eq75CQ8zhyvuAy/FjD48EnhvFCHVjP4dTVyyAEeGiiZ9Yb5XQqrqSd8iOsaN8lz4AulJNZyeP4arfsG5P7LuddUzofY+4PULRPacg/cL4A/GgvSq2AHfU+aqqIP8d+JtdLL8NYM5ztTeDKaU+IhjJCvWPsLXZM47E8rIb4qE6FakLidm2EAT74suaFyBs9rze9zCf79L+mhCQx50bwVD5cr3t5og84BAT6DUKNDM3H63/oHX89LdcQtpnz5NVwt1qVpgVw2AoF/IGGaaHxYA3k5HOgjD7X9bz9Sg07bJNk6ZqiDs2kDRvACtyKZLUxc/zGXBxnOOTz8C5UoPBtpbvgQ1y5Gru2HS5aG5oHQaqIqNhoyfxGqS4Vnm4tffITBf9Qdec0RV0OmDHFopD3VJQdtSLz2B9/ywe/+W+di4F3SG77p8JvkwqtlGOzlJK9h40OU0X+yvwJ9TlzLNIePHIam2Zx9CC/hcg5h2OqZcUkaNhzLsbkDs0/17S6AlW1tBn8hq0bHqroL4rnTSfQK9LjIc8Mc1tOl5j/2xDzwpVrKg2IP/A5WwmfnLlzfhuNB+3s0vVBX7D/pDGCHzti5m1DIMS1xbyDqSGp2hA82pRzjlIAZZ7WtnGBxs2ZpMTRT3P5VC2dMyuTewUNRZTrHg3wIO8/qeGXYSdM1dBG6PEgVToDnFqal26Hbirr7EAysbWtjC/YhPq1FmFhDtSqDZ3egp9jR+SCYd4JhpC/Oh/C3WjwwCUeV37kuw/L3DZsS8T4E/ZcoaQto/qgt0BkmbtL2+sH3NG9a1wp9CON4JdGdRTg+9j6cDrZ7Ou45AwVPdiS7wzql3D8h8ApV/PU4eJCK3aK+zIcw+dbS1g1JU3wPj8NzI6/q9pT7EHp9uW90YdO+Nzw34BpHb7Aj5GVfkWSr8iHuMXE8OgAt3l0gk4bMHp7PrP8dv2qtkgFndy/nv4SUvh6sb6DRn7ke3zrEizT1ZATc1aefnQxdZ59e6Ya/dMLuktYjjhIJ3xmgx+ALYy7oss2SnteMOSpwlK4SSu677N0K9Zw/srK1oE8kzJqMoFHeV2lbqP8r6JkHPKfmOzjdhucTKFRdhV0dSxV/IRPPoxXFdsS3MbnUDV52FRcOge6rbUmxcOoyl3celJXvX34D9VbijFuhTvvigb/wyvHxr1Id6JODSyaKMGmB7P15uPj+Xuj+TvSlh/hvIbi49MFGCr5+Ny9rDaMMYgtS/33OHM2fA+NS4hPKoduc8n9XetEvA9c4LaBUgmesM8xRWbrSAB89TRxQ6MPcGg565QoD/l4UDoRTP0XTo6G70Xp4DqzpmiOtgKYM0x5NkPe8iN4fqPTEIUfhvQ9xgLOBTxO+seZJvgrZ6OfLywcRT47Ao01wY0swtw+yjg/RsAxhXzNIt7sKV00z5yzhCYUCU1c4wiFuQjWGPntxZpwFRjPcMBCE7IXBnTdhQfh8fRq8ZGJyOhdS0k1VV8CSF/9dtllF/A41TrjD37GLt0IhA8t4YhUMaLjZtAbvSHzU3rmGuve7PkYHFbj28htD55e9ebbwKG/SCU8oO05t/QrqMbcJ/YCH78wXknz3IeaqGRUYoM3tYV0vUl9Ce0Z06R4kVwwNfAijwxf3P4O/G64UFEL1xS7lGnjvr+ZYJ3y7c8D5A1z9ZkE1D8X4cyTXoctXzTZSMl+iJ3vDmBFq6OT95IJf5m5FisEK26OCJ+CbiZ2VKvD36RGdy3A+hvLJOzjE5GCiTu5LWAmv/tKDfWLe0eaQi4dR2BnqkOS99YN3+i7qRcL4WJKvKbBI8XVINhwuVZ4vg/RnGPwb4fWaKdY+2CFaXTABf10VZ9dj9iXGiPjKG1CZi/y6E+QYbbL+CEXMIixO7/UleKrCd52HfPTxL67B/klPDRcBX8L5lNdPf/gpJTgzCj786JE7CZuOkhpJCPoSNan+1Kfg5u7d5RpwwFBlZ76kL3Hqnk5ZJdSotrBtg1f0L/6hk/IlZHTswi9C27UZRRP4PM1iww5ujjqK8cn5EnvsLWYPQ176G09OwlT2kkgXeODWvEwFrLneLLACHzQqTWzB3hOtKdTyvoS0nnPQWUVfolqO88xFaHa0m9QEPqtbJ0mEe49uPumCezr/mo5Cbw9a/gXYS3bUM/WSLxG8/5dyDvyj3sxUAeN6TEaoL8OEa2RGsJ940m0D1XZ9e+QBBz9GMNTe8CW+kW5/7oJHte5UjcI7P8pYmM19ie98xQ0GMOLL3RQr+HzUwukOfLFLqeCciy+xRfo7+ioME3/teBNq0/8pfQMPZjbNU7v6EkEy22374d2NU7kHIO1tU3XZQF+ifGBT6izUs0/jvgh7HNc0xuHFw1G5WkG+BN2PiYfX4PU1uUBrqHkww84NnvBYzXSM9SUYfc4l+UKD+vzICFjdZ3X2KxycfUyvE+dL1FFEkxvDJ5ahm7ZQ6YFOjF+mLyHJfzEmEpLuMIx5BIfks2K3YWz68deKT1EXq/xVd+FsslltF8w9oVQ3ClmExOoXoEDta82pQl/issua3gp08ZQ23YbbYdQJZ4pQD/d3tIfBnsPZ/YkwQNhgIguu37MdE3+N+Kz6fpGHM4Upm+qQSvjmsUCoIakQ3AqHLMvjBuHG9xNPZ2DJSFPRGty7/1r9zjd4nnt0JCcg6bErAnYwJf60lBcUOSd1JgzKRZVNR9f7Eu1vdv9Og9zK5vQvobL7G481yGb7Ikm5AfVjdDv/Ejyer9FoCk/cuPmksc2XqEwPqeyDp0/mDUxC39/GLjLtvoTjNZG4aMj+sy0vDZ787tqaC6tG9+fO9CL/VY/a16AAucjizj5f4ohwudUJmCXzac4JznM07PKHmtZ5wlFwhOuJaipMPJF+Mwee7+XcvQrzMnnbld/7EoqJUYuXoPN3ChozaLzOST47guuZ/xD5AZ8QA1qkH3yJwxNlU3JwzMrhjgsko8t6FAB3cc3URsOpOFVq90+op6x+6VDYf8DGOB7ucKwwXoCxouGyR6bRlz9jTRVgreSzCE0ocN10VmXRl6Au52fRhWKhy8o3oLmTk0wOpDr2bf0TVExlO7AKmdw09XZ8QR+q5iX1rqLuWe50TcBFIzXSrzDqyyq1zJovYVduOGEHn9ZH7vWGC6qt6vehqiqtXxJsrr1a8h+8qG5TswxJfqV0SH/3JfYVaZOcgflzDMd0oPhkJuOB374Ea8QFDWlIX0YRrARrqPdMJMIKV6KlB1rTGJFMwAjeUPllSGXarP/fH19iXJc7vgTKt/t118OSRPPqP9D0EfVL6S3EK7JuTgkm/A0Q0IFVUWQZ7Dv9iBcN99/yQdI3LB9FYPoEm7cmrNnxc9MKSoUUsjtCxU4nOTf4NzSGnYvcD3FtPikIz2fuMBaDC5T75lXhKcnaqlv/Plc7OOEEFQQSSTxgwb3CfUWwS1Xj+GvI1DFnUAvbf26JfiH/dx+bfSwUfoS1wuA6F4zwKdsvBA8/zeEv3+1H0NxYU30LXRYU7Jrg0UMUIgvQ5IbbbVoqP2LYeSOFGeZaNOkdg53q0f+ZwfqfZjdC4UTQjj+Z0HZmhjcHMtB2qxRCc+HlpSpGP+KySCxrI0z8Ia/UAY3H+llXoNrG3PIeJj/iRGDzfnZYiBcJPijMd3PlFLwg9qjZFH53zV+1glr3mzkdYeas4HDnXjx/bQBFP0y5OS05CqfoU+Z/wZ1zGhl79/kRH9uHOjngc2/rTX5oX/Sl9MQh+OPP2mkou4fpiBr05XkoaAFPRj6/mQqp8hyfNcB2xfGpdvhf0XmePvhkR5PhCKwROZ0yCS9IhNHQivsR/Ccpy2Vgcnztj5PQoc1P8iys3Zd+eOAIjou02I9BEvb1/Gn4ZVTg266jfsS12JEBaVj1XZHlJJyRKtA7Aw056p8NSCNPt1LmxmBhipvoDPzvCF0VgwziTKFLIw0t623Py8Nok7AYJSjeUWXpeNyPaDhJ8tINesVorPrC7YbHlKlwKUyV8zWMGa0yrYXBjMeet8BWkbKld/CazTTpEmxkSTVmPOFHCDFpZrHCXSs7v3DDpS/dlgGafoRGXMLre3DuoAntA3hovPJK3r81l9fPXrhK56Y+Am8tu6VOws7kV5ZB2n6EVe3BqvuwaPg5Uyz8mtN7swB+6Ap92wn/Whzd2w83VyatR/+dr2+n9ELfj7ika5H2Co6pmW2Uw5DXd80HoJPAxoWf8EIDX+423LiqTUlx1Y94fP2DYJoh8v7LM/AZfHWfdzIXMtvc2jP8bz3SZPUbSrE/b955HfV1KVJw9z9D3QMZYIIiXeITEz/iYLHlr2wozdt05RVk1TZPGYO7VOR8SEz9iHWf/vHdMLbQRYERJrDGUOSa+xFExTOrIvher7rjNcyu0tEfghJZpWpbcFZi50syCz+iouICAw2UnJRhv2uLfupLDoyCVK2kXxJgRMVwRDFUE+eT6IWl8uWJw5Bc6+LOSWhI71V9xMmPUE+iPHgc1gsnxhMwLI3mzHUYn2ey5gnfO3AbBcLOY1NtYfBR+V/7vGA/glb/7VwJ3KAKMqmC3f6tZz7A1t4K4Q04wJf7eEcI7iMok20X/CX6e6DnAfpC+KfeMIw8tTE0AQ2ipMa2IceTJ0acMX4Eb1LvhAA8m01pKgbDe09/koS/mf1vyME4h8YZRTj0X9uSPfyYYvE7E7bpr3rmwANHArcKIZmv476kJD9Ct6HsUQY0O0DK/xxK9LfUdcLlLQaztX/r7Lj53/Ak3z5G4WQ/4tzUooUqTNvjuc8balvT+WTAL22U5M/hJzWK8HxoUJD31yPVj0j9nHg3AG7L32UMg2Ofo1TK4PoH4scolC+x9ZmGo3nplF+gPV3T38DHfkQfl/39+//U5mSJhZfddiu/gins6q7v4PcQoZ2DkGXvrohxqP+5UpXsiR9RmWVLfhC+Lw59cAQuz2RxHofKn7UV7hfiOZ/HDcTA/x6O2ibDeFaJ9nJo/kJYZBAOSqTXjMP0abYrn2Fyy++3/1Uh/iG91/Nhzp38rVJYp6zn3g8fLdr+WIMOhe5xm9DvZZgkabUfseMB1ZJxrR/BrmobeRPGSfcfdoAe1NklkfDwJg9FLmzsLfuvCM5OXFR7A4f0jY7kdSJOxaIfSuCi5lZQFVzdvOS3CPsHogvZuvD9iVnX+ODth7UUB+GgScxGSo8fcYyNLisT7t0TpZMDFctMX/X8Wx8nv7ECD31ort/X60f4pz504IJpGTacQjB0WrntEIzwmvY+B9+Hb4w7wQb9XeEesMyS43gALGg5oJ7Uj+d5dn0jAzo2Jj9/Dnfr7Nv7Dh5sr+ldgp33jgT8gOn3/zuyBV9VyoqYDvsRxwUoPlhB1p7hcMd/a0UNikTIFHDhaBNUmfqU+wWaV/VGsI34EZovuAk+uHPMcVUE3is42dA8if4O6vR8B/0zTSUH4SfPC/7kU36EjJ/ljhPwRoly+WnoLC3qoAZdz47xGs74EZManz7cgELpy/E2sHLy8WoybKIqYG+Ebzd+93fAbmmN6Pfwb3WG+ihMVWfMpvqMOTGfqysL+Y1UGBXgKu9suzKUvi6qbTaPffPXKu0tmD35ts0JbrIweCbBt01f55ohp/WfZ+8gmyGd2SB8ky7I8xGSH1Uc+wz/lPNE0S6g35KS3TWg5sqCmBN8ZW+z4A65Fdb+84fx/VkGJkuI404xdivo5VM64gB1q18nPoTWJUIsTfAj1beBTuhSWJPQDxce119y+Ib97CITixucuGIx7AuNKxen0uDge66lKniu70l+47/jQmJOnXDW7+5noy3sL9HUryyh059YT3toqLT4LBIqRm2cL4FJsWVsVXD/d4+ZBsglN3o/dqc/wRqjpJ8CX6oUCGVCMy0X43kYPLMUcZjEn1B5WmMgCynqEkUU4NkdqRzJ5P5EY2Prl8fw1pfNymwobPSKfgVOcCdGyVDgfD8J41Ow7HSXhDLcFvt64MVuf+I989zvV9DU+HNnBZy8pFkzB80aj909QOVP2J2XJ1GAxx6n9CtDFr0d2VowZd2WrgF6rghPtcMGrfmSPuhYzEO+Bjs9cz32UPsTBaapWuxQPC+Wjx/apc8IvKT1JzgkH/8uhlSHTLsrIbWtft8ijE1QfbWfzp+IqT8fygtZ9a4ZikARbTvJI/BCfDtjPqM/YcWrsVAKtfZ111XDO7ZGA0tQ6g85014mf+LgaPsCBxQVfFgvALmjHttp7vUnNL6mq12Gka8zBQzh8kru3xvQLubNiA3cl/6uxAXO7puP9oLzG5Q2QZBHVUwlHDK8+TgTC2s+0tWmwGJ7pUeZ0NaQQWcBjgasRh3b509Iu8XeIqDc8HEVVbj2bIbvAkzpOF14b78/YZIuFv0ALn/ksEuCapFM5x5Dho3+X1+h+na312E2f+LewCEDWfiLI/q4AtwKOl90HbJbHNnyhjwRDR+CYSif4esIuINdeP9jTuTx8czGc8if9HykAPLwB01+hZV9JoIyXDheEkJxCqpRvpo9CyMVZGhf8foTd03qVsqh2/rF9zXQ/NPhgyswayvnhDCfP8E5fo9LAg4esSU5Bj32q++uFETeSjO+1kOZ1j/97XAPFbvuGiTbsVjFJ+RPxCfcfXoQfnsiev8ojDi5nzA87k+I3SCTModjND8O2MLpn78X4yAFyc3KYnizJqqgEjLsrHraAPskzsnRnPAnDO8VHGaGljfYBDhgjbbPghIMJI0etoaXPWW6nOC061SdB+SaON9KqeJPaIYVN9H/8y1XAwsU8I2s5YbDpo8Lz8MdlJb8d+F/xgK80dDh7CxXInxu6l1RpuZPKP+qLn8L7dgoypvhJevYor/w9s9KSgl1f0K1XZvyGPwm+oWCgCIpo+RXoOnhCHJjGH5BifwmFD8uSBYNO6l509/C3tb96c2Qai9r+jvYpxr0xvKc/7//n6y0hz07W6ruQK0g1sb/YLtPwp9BWGxIuv0RHmx3/TsLzyoXpvKc9ycW/xZnCMN4tapMCdh18ETRFTirpEvtD2neptDdg85tnxkfQElBVck2bX9i7if/sV6oe4385Ai8RttuxKTjT6SdspFRhNqpKXLqkCaym9CByR3RF6zhU/LRy07wXbeYgQcUK/rPIRkW3oskqYRLboy7GqD37yTaDli1ccY46zLu07LLMg9qWhval0KGJ2Kpn2FPcM/5vbr+RClDth4nZJMIMRKEwvpnr2br4z6Dk268gk5qa3YV0O1U4Mt5+Ozs2Jf9V/0J+nFtPkV4SYHhkDpskX0vqwP7d3IolRn6E3S9py+8hXlytobN8IlacvpXuEG6Y5T+Os63MZtngbL2HevcsMLv1tdYW/RDQwrlI1ia08P9FPoH33/1HnKd4JLaa+dPvHr9/BwnPPXxmLkgfHKm9nqioz/BfK3aPQM27q+New6dJFRlh+GqqJQEkxPqmTREgw3q+o9Z8EGrq7svhbj6Eyvx9Y6RUMkjMCoBWlGqvUyDGe8fCryFaRWnH32EsxIWR3fdRj1selxggE/s4+1YYVVDnXKeO+qWwcyyFGpS7r5bDdNnU0Rn4fmFdLpdHqjzeJ/DDFDti+kFVjixfM6RB8qlyscIQ6OfR4ok4KCYlbsJVFismngAb+/Y2pkMa2pP8z+BMrHj+0V8MIe5008egYn65ibHoX5pErMp7CmxaQmDFA6OX2Lg1JAnQwqciRN6TBKA6wo+bKaCDZa0y0wwhL4wTw46i6ioXYNhl9ftb8D6ozkJNlDv5wOm7WDEP6xNjiIE+eneZU4HV4rjJWWhwT3/EksoJUf20R72ZITvcoPjBZ9DbV9if4h70+EKq84kMPpAlkjJ72UwQLxg7BvMm5vk+w3vOOy/SZKH4zqlD+xfoa/PGgzfgaWUFLx+8BnrJZbX8I6PMs0C/PRY8dIqDIk/8+g33Na2ddlT6E+8CQmpZIcd95+RCUAZk7ZzYvBs3XDJZSikpHM5Gu7Or0tNhNGLxz5nwGaeDwc8StB38npOAXBCZLgyDA6SGnlVQrNrq/VfoevWW7pf0NQxVn9HKebv0Fs5owqcd+rnXUvY7iE1YA/3ClRfSYIx1GMf6qCC41WRdqiZO3a7D8oMnvIVeo25cYqkUxxSebWzyUJbScYMY7goscMlBt50pq9Lfv3veQQYMiF9X1iGbRWOf01ZcYXhnwoJH+jIp+afDotPatXVwC8tSUytUEhs0bQHPnhyqMGmFn1HS8fiCm0vfrfyhjmrzSVpcHif0OUWuDCj/LwbPo2y3RyC7kVjiiGN2M/UMhIj4dKbm8sJMO5BwrcW2GRW82QFtkq/+/ULSs980trZhL4V+3BREibITuTaw99kKqRukK2gSN8PWgk9eJ/YivlscOTQY0jqOBicDV2DXsy1weJSP51P8GSOQc4ifOcrT/Yd2kvxG/6BfK30pWRtyH8vhbM43AplD7SCE0/l58Jg2cnQ07FwR9lgcsq/z6nPa6T14/x8i9ws2HsiiDYfptx1WBuCOdzP3X7DwYodIyQD/gS5vJEcNbTujOS4Oox8HVX1M4UK/pTT1rCniWMwDmrztIk3w9Vb3THvINuT0fVBWP1cPlt+BO9nrfG0Z6Fr/3dHTejfJ3zzDrxsmlafDSsdzwgXwtM2K+Gv4eZwqubVMfydn0ixKVRjfsN2C7oNLbLHQ2WOOs63UOhjXFAzFI+yXXwHl+bFBg0m8T6zL5y4AYuOfsu2gdGtShUJsDR46mgrlBmPfNQDw4VOU4zAcveBiusz/sRXByohS2h49UyMPQxjf5ufBB0otcYaYPHVVrVO6JShXtoPpVYHQ2bmMJee3P2xBD+oKNxYh2GTm73bcE/E9K0j8/7EYd9fa/ow4sEfU1MY9+GtTSqkyZ6mGoZF+xQ9Jv997v5sfh6uZ3fpuC9g/9BKrfOHDbOOR8PgSc1Vk2LYxHpOYhxmnTbN+AwtjH0YvsLEx4/6tZaQL1YbFb2lf3PgdIURfPCFQ/QmfJ1WPZD8zxFZvQEo1GHROg5vlaTIzcLbB5u5Nlawn945FLvzmz/xsTqJkgrGtDBoScEg1UcmhtBFS33AHCZpbavbQY6NDzGJMMqs+dd7eImt1XYMPmrvnpqBZmoFGtdW/YnvLxhrb0AzSncZW3hIWYcmClLmDHIUQJkRl5hy6EHGuqsWtqz61cr9gLMLx87AqOGrBecgf0v3gcvwdIfedCI8/GiVcQzW6XXdm4H3GAp2LkOhz7GE1gbi8n38tS68SyIhbQR79egjk6HcXM/4GGT9FqD/Gb7fOP5+Gbbsly1T2UIe7+lIXYCOm86vrsAhXQquOKhG1XS+G+5PP905BK1l6tUnoVK3ess8TK8oUjm3M4Bw7cpqvgS559JVDOEfAdaWRGh8qqe3F0plClz8AGVpffo+wa/BXj/OkwcQw0Gqbleg6n22TWPIqR1MEwf3kXhbdMODLpnzQ5Bt+Z3NJHTK+vZKa3cA8aPtgawefLEhW2UE5eZTPsbAfNdk7XfQRTp+cBDW/I03nIBvaG5xCNAGECN6dU/FYGU+9yFpeDGqR0sPxriPa8fAt+bbNR1Qt7hLrR/yMTzrHYNpxdFGmowBhNDc6MJlKC96+PZ1WEj+6PUDKO2vF/MOOmZscw7BB+9ysieg8TEKmkCmAIL+hVjifcghpi8QB+NzYyar/7mecHEK+nLumFiA5Jftbdbge9IPKTp7AwhRvr8iBrBOR6TcDL5ef0b7EFbG+/C3wtiSn6964MbsbWIEco2UN5vvDyAuXKi7Ygd9P/TM34ZRI+fEk+AxVzHnN1Cz2omsASZxvI3vgOJGu8/wsQUQ554n9h+EMxTilpJwgc9F4TosTooM8YOG3cas92ANx/EXD+Dqn9p4T07Ed3+hSBBU0HpeFQ456Kpp86GwuPnqMFTUTgyZgrrhPWyLsHT2eRwXF67XTiNyANI03646DCk4pzOvQmcHtvvB0P1OM3ckXE7wKE6Aiy5hG4YiAcTU5y/xFjDB7fJRe7h+qJJIhiUTpBca4a6e/C+d0HDS5N4AfOvq4bt9PIDY31V4gPJEAGGt/e0dPfxII+J4FGqd0H9jCJNt+s0sIE+bHo09/PH4YLrW6QBC/0LSOT2YLU732wguXC4yvA9PBpHVlcJTzlX2b6FLjBdnC/xmvRiifBbxfSQuex5+3OE2qwdrAwp3h8PsBl39MsgbtrC7BgYEBL1ugYd+cnUoagYQWfv3BmhAURfGY5eg4SEfr7vQz+q+eDFUs+idroQ3U7hTGuHMLmftLmjV5f6GQyuA6HCgdhKEnRqZwuLQcZkg1YYXalKHXOF8km2UDzTIVVIOhbwabx3UtNGXk7EiOtC/yG7qKrRxYDoWBdVdcq5UwMVdPYx1MHXoT1sbXDAv1pW/HEA0HLvGdBbuVaPq0oTrpY+lAqBW/DOuUljZ9HSkGq5Kv0hohhk7+ZXWIM205t9NeIvM9w2ZLvpRtfemBOyMML56Ea6wde+7BtU+n+27ASlFIt9q6CMvEpw+lyCne6G8IeTP+v3jLny8TfctB+q3TeUXw/CBSrsqKM4yZip0NYBov7WL7zCU3XliUhaqVkSlmkF1N+6UEMjyMOpqFPyxTs6WCPEz+e81Q/SZEketORSiTQ6wg3M97+4+gPf4o6KKoYjaWe0qSFa4c08TFOP6fmfbHPXkmahAaYG48SpRMsC4ODEhSTghmXxWFyrf8qY1gh2LFv2WkGH4/beztgGEREZ+tRY8XBJ9Xw/uzL8UHgj3mSXVZEH6oIqIfCi89vFqOdS9td6wDTOTL8dQ2qGvWN8YMcAxgb1m8jCkx9DyJqzI2yXtCGNGKkg8IEd7bFy5H/Jfb2xfC6/uk1Jvg5foi6PXocP794N8/pjvzMuFonA9nzZSCv63j3rAGNa+d+9Pg33a7kp1UImMnLsdpjI9/N0Hux7TZh4ODiC0L9L7H4NsZixGp6GT9p3BG5A6zPXCXai/WCr+AB7M2aZJhtWyBjmSMQGE/f2yGHl4TZnN4yycPTHDYgV5LkqWhkOFgnep8XDYxSk4DUZ/spJtSUTd7Q/g74G9rzPoR+AnyeRciqQAIuVciow8PL9FwX8WZjf51zpChQsZxmnw9H86mv/BNGvqEwVQqLE84ydsuZITsSM5gCDRf+qxG+oltogfghb+4fb6cKam8ZopPG1Lrn4L1hid+RsJG8WefnkIWy2oRjLgAO2d5mzInVYv+Q0mlBx6diwF+U+ljD0N3ddm/dThk9Iuu4v/1kM7X3SmBhCbz8qSBmDVlPO9j7A+UsZ9DkpJSQ6dTkMehzekY2Cq3EmhFDhDG7rvKZRrZljoeYw+F8sZHYEBpOfefYIl59Zqv8C8vPGTyk8Ql+8mhzLgzbRonmzY/rpxTyHMeXt/qQM+0+Spn4KN4QGlizD31GL2d3jd7GrqFpz+/S6aIhNznvxcED30Dei6wwofO+nd4oX2LPe+i0O7Ja45WWgu8+YDAfVXDd+pwU3xwfDBZwFE8C29gAk4wTF+Zx4eFA5iUMoKIJi6ogXi4MuniWypMGkliyELjr56Q5EPuy3q58ezAwjizcGpWagWmjiyAlfaaPo24MmQ0HaSFwGETMWuBmo4aRZdyQyVzVjU1KG+B/vBUKhRtMUXDTVvfGZPgl9UmimK4c3h1r+VcM+n3l+NUP539LtNGKq5PCKZg/3ZWeO9PPRnyu88Cxv1zA73vwwg7jJkHRyHz5S+Cs5CsqFLe6jz0OczPLOqUJvBs/8uTL6m0PMAlvFTdSbDWa3AHOpCzGm67mxmKHGO/zkndBkQyFAv/HcfC4l3/n0eGPzQD55/IpRwDw6rpxRsV6Bf6J4VU75G/i6VlDNA9TDZVikYJec2bgJ50lunrGFNMO+sM7QzPcKTXInzZTiFMmFAFL1YLsxiPKQ+DF+FaZ6lrcJ7AEekxj74VLJfmxtOXOdf+Qk/utH+3FEdQNiybm/thovtB4UJqPnkkLcbNKNxDvKHxn+q74dB5dhrluk1qBMmCYfnkGc/lfsrKOJT9KgfbvBPtJLU4j3SdbOXGr44zznKDE1q/Xv/wrC1i6O76jAH88Q+M8L1C20sCjClbCdhBlmb2dVt4HEj+UuukKy+Iay7EXOHSv/hMJweXcucgmrc1z7RN6Ee1hR1pOEnaW6jU/AwKYmNCswYdZyLbUG9t5L9fARfKKWRZ8GughrDUfikQdCTsTWAELBiDmOD3rPc/Sqw+MZeCR94/oWOQij09U7QioaHaQ+9S+lA3V7LmXgKNeUlVl/CWgpR9Q9wsCKxmLET++AVmyY26Dq1wq0Ky2eEPVyhS+mZcB8YzmKZFgpJ2uf3xnUHEA+TVA6mwuLfOaeyINcdsmd9UOhYEQ9VD94z3S2k98BxTR51Dhgl3jHUAnn9dy/3wL2WmqQfIPUnu0DGXuwbumnBJ6HCgSMpyvDS/baC8zC/LtScpB/74xi7NzUciyyNY4a1LVzUirBkvw2pBxTsvsweCMM4lCXDIUtSydp7KCM2ST0OQy/vEZiFDKsOqcwDmA+6viyK8OmPjcMa0EDUU/USvODvX545hH3uTUlvLhSLWPlSAm81c+qOQP388tVtuGNUnHbXMObE45wDjDB+W1yRDT6r5WtWgRSX7kr5wNahq+dDofa6pHU0vO81KtQN95ssnB6GT8e3r01BRvWWafqRAOJE09SOk1BzSIFDGeYEZsqeh8pGl0J/jwYQXv0vn5KO4X3gM20dDTxMM+ykBD3Yf0V7wDGGvLxA2P3YuiMcBlg72NOM4/2GPTpiL6S1Ks3hghylDwSUoOsSc/IN6FB2u9wWpnF+HLgNh/iGQ7cnUL8VnM8pJwMI5uWbLQywvub13H44zlsWpgI9u/q0/WEdtatTGLSe5YiNhf1PfdR3zKAvfj+33Q0lVoajmeDD2bAbajCfum7vHVgYoXjcD44XtF67B9fHsr7FLODvzUZZH0HnSFbiGQyjzibrg+4cC607FvEeeM3+225oobjJugeWNVI/3LmEOlYhr6GCN+zJ5/fAaxtWpafhMs0JA3M4XeoVZAfjKZte3oEWQZvSIz/QZ49MzT/BVJPuuC9QK/v+pNg6flexOXLZwcIdSlp34Gwsu48f9AjiCZrYwP7Q6Fw6D81KO+dWYaXvtprk7wBiTY/osIdO0z+33WAfT+mRABgq4OH9ZQt563hd+AMeESKZ24Yr0yeEZbb/vTdzLVvCs/pV/I6w47apvgekpPGyjmQNJO7PCxY9hKfDBzYzYFT7KFcTFCNVuf8dKhjIvd+CXW4ynJT7AwmjKdWr93kCiUOZTc/j4JC4xs9USNep4tcBpzoOvvkGU5XXdm9Cn/t1V8h4A4lGKe+i+wKBROibz2Tx8C+9nm4adLl17VE91JD3l1qFiinSIZtQpmVlkEwwkPjqu7YRKIzrSStpRcC110lPEuDL6ALVRnjubUbSd5gmr7i8BZvCFhQpRQIJPjUVaj/xQEJ65YfZPchkk1MZA5VaPXvaYNtZ1ulfULCK+yTJ4UAiY7d4AjU8UKHAEXQ0kPhpPX4nAtp+D+xL+KeKUFojZN++0bj1b/3sGi+lZCAxWuj7QAxylLfN6MOAbgpFMyhcq5ZmAyss8+6+lg4kitP++1wPM/L/O9MJu7ctB+lkAolYy4fBqtDX4ucnbVincF3RANKqN7OFwenTeu6xEA0z+Ai2bCu/aodmP15f2oSSh1KLyGQDiRGFECY66LV6oqP+eCBxxEboUCcsr2ONHIBJc7rv6U7g/uMFdZRhgYBj0Xno8qCeWR9+/dKp2n4ykOibyc19D29VxzCMw969d8hoTwUSUj/OGZ6Fp88F12pBvcAGwSvw5sZz2c+agQR/wKX/vsJ96xQsG7Bofe8Al1Yg8YUiK/4MZK9NINeCzRaRrnqw46Kisss11NPnlBpvmGb350Qo/CzcIPASXj2+g74PfjRPvzcKde+eJfsMKVMrQ0yMAwkT71+kt6Ccrpy/C5zjW13LhE+sP863wm8blpZ9kDrg5/Qo1D+Qs11qG0gkHysOroHfNRpo2uCvPHWRFfg+yFt1n10gcSW34x03lBvg0xOBFtxiG+mOgcSdjL2B2dBViIK2CD65dr3vB3Sm3fos7oS6/XDe8Rg0z8vePA1HI50eZbmiTt/qiBTAy7+Ol1bAi6vHyNagYgblLpnbiL+adrwCnPr9mE8Nlo0uXXZ2CyRYno5Ne8GLru+dQ6AuD4NCKWQc/bx3DJowCjz7DD9cuCm1AvMaAm/luwcSuR8NNsuhNbnc/Too2L57cRMOCexXFfEIJAo7zw0dhf/5h96Uh6vFaTyZ3oHE/LBJUS70phFTLoW3DLzLvkIbZ1pLSZ9Awt3yxG95GG5lF6EMh9+kVj/1DySui166lActchgXyuA3Shbbb9DHyZFHLADXaw8rlYbt0jnnFOD4HsHgtOBAYte3Fs7nMHHSufQVLOek0liERzSeqrCHBBIJQk8nBGDF3hx3cZjJWsF0DH55xxyWcy+QeOxWIlgCc2QNa6thkyJdxzJ8E+I6yBWGvjh5y1kYXqK6SX8UemQ1xGVFIA6ClyULoEP1l54K+FRKc3Ee5r82ImeLxH1bn33KD4ckjyodgk37hKZk4Db5pS0LaKi76R4B756Q2f8Qxh9zK8+A1ze0XQyiA4kLA5PM5tC5y63EDpq9ZT8WD93af1dVQP+Knuv1cLsu/28H3LvcNpzxIJB4fvuc5wt4lb2foxjaq6R9XoJWl9LzRGICCWaroAuS8FSyw6o8vOV108MMjh8MbguBVYavbKKhyctpumT4QHiTNTUe11uyq8qCrj3zJgWQotT45AKkdM4NP5CA+H0JPHIElgSbDpyAjhSPT6Un4e/kdn1+Dr1jbkcUwiNKu/umoDtXTAhHMuqHTldcCHLy8g4chvt/Gic/T8Uc+1F/phDWsop/fQNXVnOUvsCm25OJHGmBhPaRZCUhSM94dfkw5JXndCh6HEi8PuXNWQV5rKbbmuCVxy1+SzBPkXi250kgEfd+VocTRkcm7DgAX5HR2bvA58JbHD7wt8taWyhcjzr/sRbyP1AdWoWz9XEhf6AZ95wURWYgkZ3m+kX1OeavVnGaDowR/X3hGjxtqM8WCJ+mFicUQbITimpVUJN0cLMJXimelAh+EUjUf2iejoS2R0oSE+HFuHqOVrhyhEt2BYbpXVzcgHk5UemkOYjbjWNKbHWBBLnhw10CUD9+q/MQpGOOk3KC1Hn8bblQz/RrVCmM1K27XAPvxTyIEGoKJIKdvl2WgL/irnCdgDoHWnfdgkO3Un2fQdE8A9V8eFGSl7ECej0I8RZtxf1qCKhKw89qrUwKUHtGoc8d2kjVtr6AbrZVccUwZrHGqBremef9LNkWSIwtBr46Ccskl7xU4GGqDy/s4FzXytN0+K7riUM2dGO+Jl8EP73O5pPpwVqWWFOA/22P1avBJ4rGgx7QLKisPgfuC3gWVwIr2pLN30IXt6vx8f3Yhz9JWKXD1Ud0J7MhS3u38Qgc2Wnmv3cA+4ZZ4mVuGMHULyICdXsbSY4OY56c0xiWg5UsQ/lnYWET+eRteG6FWT4NZk4uMD2HTfwt86+gqehdjk9wK3fMjWoEeWYlu8D8f8X1HY51F8YBvMgI2RmVrUJKlJlxKCsjFSKKkB3JKIrI8+Ahe5RIW68iKhklIslMViKylRGlzKj321+f65zrzPuc+/e7DnTpkN8qDN9HbdmU1RtOyodnZ+9Dz5TG5sdwc/pp5S7YrL+stOoz4jTOy8UCpQZ2T/BAhc6pyD8/sB7n8dPMMyhbf7PmhqcfzetsgiPa5pc94FWWxrlqWHfEpv8dtGWeqfsICyzP/mGYCycTd3zHOeB3y7MfBGFozIiELxQW/P2zAd6zi+nvgNFsEk19c/++5yJf+Jdwv5olP4hBm0H5N9v+eVyvUBHeGLA94AOnmfzeFcNSne8vK+HbUd+8BnjpBWOC+J9wEp7CcUkWmneJ+CnBdweExM7AAQ7LuDzY9r4mtBgurWj6VsKQFQMpbToKebXhpJAR7M+O4raAt2VPfLkAr+Yp19yFHaJZLx5BNXq2xyVQ4+EBQw9GCnF4HantD0NM3qpehAwj/awvoMEt+W1zMHa+RWIVE4XIvwrcxAJN5kfYvFgo5GuYEPM5GBBmS38JHhHw/fIS/lk6ev473H3uZ8ASLHNPPrOGlUIiPjxx9GWnEGemiRPBULlAxj4ShgTrWr6GHdzzprNw97EEk79wWETeeC0HhVQ83xtwUoZC2r+dpHnD4rz4zEBo9ahl+SHsF/b3+QrfBi1SZuCAI/XqMtRl2u/EuZ9CvvXvjN8A5exEnktC7wtqiUfgFX/blBR4KC+7IguujV4Y/w8qp/GeUTClkG1TfDfVTf/NK/pOD3589aYwEGrRqWTmwqcqafVFUI1/eeEVtMqouuxoTSEx93e+PgW/OGYvnoURyvVtN2EHn9ejOrjIID3SBpPvTWz8DKNvXXQ6cYxCerinr3tAW2XnTn9YWBf/Mgtuvat59y1M5fvd2wIvqlfw90Atz8pr9iexHwXlbnf48XGhoD+0m5znz4KKdu0iNZDZ8Yrde+gg6nCjG9YqxPd8pSIeaim7f0Iaz63LKzD2pqWufASFHGXYa3oa+pXkZQfBUQ3RvxRYkd/mM06jEPXgvsZfsFjk59a/ULa2flohGvHy9VPxgYy8o8nnoV603TQVhoixe29No5CFAts2eVgn/FRZHeb6Ts5R4A5hgdlG2Jk2bN0JLaZKygfgSr6Lr9I1Ctn7tK6bwJUru3SMYICfeT4Nfr6U9O4tVO91UGqF5wX3ZPXAQUpJoXoWxjHdKqIPzZav0w5C+hbWtQkw6VtmQDMkqkEDXXDIzc54GN7gLHtCu0Uh72MfiKRAjpmbl7OgfHQdqYUN/PkOy9CQ8quZ8Tb2+1FbgwveZd1jrwvjG4ubDkBBf/U9R+Gc25/GqzDw/MqPRtiyesCuE8qdbmwagH0nPi5E3qOQO6NNrkmQatHwMRM2K3Gm10ArX8H6Jbh+rbMaQzbiSXv+gAMyRZ7f4Qgr9PhvnIJqP55znIMhb6+23oJ+y2JpDf/aj7ExfYDbK/+e7YdTPH1rOusoZGLFNWEA/vy2tHESji8afxCtpxB2lVwbI2jkHPfFAk5dO+drDzUC9NsaW9BOvd+pE9ZzhM0NwB2jQs18rcifnJPDFpCeyyXAHppRTzN7QKqWdPPHDgqhM+x0HIItJ2IXvsGe6pR+8Q8UYh/qutsEyu/2rjsC8+eDjztAOw5nSY9eCjkl3lXuDx/uN7cOhQ2HFI8/g9Hz/Y7j8BfLsz+/YPZOS3eRzxQSp3/pgyHUE77hYw67WarZ7CD9j6rPHiMUcsbM7GIA1G0YEQmDzk379xbByQ8SlbNwNnODw6pRxD9EkJ4VZl/IVLdmoRJFdodFRzjWKVfkBct4CpzvwqNJs/zd8N1boY5h2KRomjQNWR+zXFNkpxLZxWprAgMuRAoawYvU5o+hUFu4/WoRDNnxw6oSGgXxCTbC+Y0vAg/xUYmLXa7WMXh0+B6DK/wS+VkoGRILLaVyqCsdvlwLxbWaq9qgYlSwjYU2lcik++vYQ991AdIe8MKrhjdpMC1g0LAJ/mxSkv8IV9OSBYZg/O+NataGVNJurLXVCb5i8uD1hlb9r4vuQQPhU54t8OrvSese+F3HX/8LlPiUlmC+n0qWnpwPsYNk1tXTHWqG0LhvweOC2xoaYSPVs7QTMh4ruj8I3egmJZsPUsnM9WSBbtiWs5dtBK7fsvx3GlZxv/y5BAe9I74wHKKSYA2rT5ww87xC80aoL7P+9RYYdcItSR66/LCNUIfRdQUcD2C3nJ2h+GH092fT3A5Nt1cpqMCqRS8vZUsqoTt/4aQOFDydZGsCNU63ryuATZWl95mOUEndgMsNbqgdIHxFCGpc7I2TgvRfdt+QOkoltCvG6bsgQ4VnsibM27JiXgzdNNdNCNpQybJc34gk3Jte2i8HX9w9UXXwOPbHlF9hC58OrXnpAveZGj0shMY7t0uus6OS6mcs4gKQr+i7iARMFa/ut3Ggkpd/dgw4Q1ur2wM+sKuceeQpHPa8vHW1I5XkZAdIsUHX427S/PBS5I7eC85UcoKtrj8S/uHyHE6CN3ea/CyHv0xS6Sbgh08Uxjn4fvwCy2oXKnm8mKE46U8luwQkdOdh2esn5nQBVMLvsPqOKhwKlRo8CW8VrJs5DWtO/V59Ab4KlwxUDqOSsysuiTpQZV1hjgm0lFZjDYLMju+pjyH/wTNZZTCxY1PxW/jo+IjUdxqVzB0f0/8NyfKsM2M07nFKyJACzNi94cZxeNnKr9wNdgl29vrBkb5YcdUHuE+M14/ugxxDhUkH4MuZA5uyYKGJssICXJ/V7U7/kEoW7kXcYYcBx9KkdB5RyXjrW0cTGEFHd8MKervw0WfCosP2eyeh0jPei/PQuaXlOV0+7pXZ5uM6TxDvSz6ZJvD6mZpuK1iTcf5gJtStYMvrhZxmbRNfYUnWbZlf8O1N8d1GRYiXf7K/JdzEuq74BNSwySL3ID27Y/EYnPQyXfwF5xJ09qwqRl6JVbcx1SE/9tVJ8MBwlU5fYUgvdWvNEdiz435UPNzCzdd1Dd54EyudDde/e3xWchx5eyxmQA7u6TxltAceWrQ75gdHQmu+lEChFZ5D1dDbyb2sGcocZteXmkL/7yyFu+BoEKeYFrwv/kTnHHx8VubkY1imkdRaBjfO0JFaaLalJFllhkr8vg7Q74ONGbx+B+BMh4piMAzvrpt7AM1ZTFyKYPG2rs5KmCT7JG83XQQpsDkmQyA7jeu+ERw5JMRPhaUuAgz1cPqSyqUO+DnzxN9+eD3sGrsWYwThzPaO2//PRhN2S/isVYs9A740lYhvh3uiT3H0w/K3r+In4LvRgMv7WSLIZpmzHJbwyJnQpBOQtllJPAMa5oU87YAO2yeUBmDdE/vnkzDWSeSJljjWxzKmbwQ5a1/0WsIe4nEiE0bE+o/0w0ux5ecn/5WzObkXoBKV9nzVlgjimaF3mA3uaWKb5IcFGj5hx6AOg5DAHcjzm8/lM1yRCFs1DpXcfqXPwv1bBQpYZCJIgssqYz5YWfPjixgs95X/ZQN3UBVMbkK1ATubblhweHJ+BJaNhKX8gM4pE8I8OyLIsS2ryoVhYrfQMRkY7LAn0AlSzJvar8O28AN+ObC1o5vnGeQ698lsSR5x4KH7yaAQQaTa5VO5YPgpTscjcFLxOlMOZGEyeVAId/xhMHkFLxr+9WJUiiAHg815ueF015NSIehqn3PNEXblJ8hmwckF29YcqO+hcO4ZDO07ELSsGkE+XagSZ1aLIHp6mg08UDprpNwanhtcmrwBBSe/pT6Eh8THNYthW6nS0Agss0hN492D+YSHtUShwHr1sW1wtDNe4a9GBLkqI/OZRTOCPMhtovHBP9cdE2xhvuAz2m1Ix/Re8RFUl/w1UArla1Ws2XUQpy0MzBtgWHF30WbYHJEgZg/vb9lplw43f3Vnvwff9zx6WQDTM/RclnQjiEqcjCCjXgRpKeJv4IITgq7zR2Dd7ulDN6C/sDnDQ3hLs6q4CIZ6uCyx7Y8gj55dzBeACqq3nCThdqm2qeNQX20oMB3SKbvL3YNRp5aGC+D1GwbmyyYRZG9xEBuzKdbJWlTNA6/8/cR3FPLWZTxOgafmdd1vwh6HRfFcyJiQLbfmEM5pHeMEB4yp98reCNdqMJhZQptU/aUEeIKXrygTNrR98/kPuv7g7es8FUHOVngUDMGU4YawaWjVn/NW2Avn8mZpnSn87/ejPmvoTfN8fBJOOy99Ww6OIGZMfI3MIRFEkW3PA174dt12iX3w9WtjzjOQ73DNVDA00zdsosHvq02vs7dGEPG9CuUbYKqcaN8W2Fwbcs8bqiQX1JXAdMVNE9WwPjyRrQXGOzoasHyIIDMn/Dz54Dx7fII4DDyz5Obxr55z2vcZfHMj8molrO+VftkEDTUMF3i6cS41iSKikIFuWE8WbszgZHODujNDi4+hI+2BWDnkagsyrIfPq69FC31GHi9vfCYNR75m9ynCONnpwjPwE88ntjvwP8G3yvnQrqPM4QVsZl6htIxFktbHsZGfYfuCVPQEPHjj/RXZ8UhynGtr9im4d7NyThDM7zyYGwkb1zyX37cUSbgUS7UPwlmu1wePw/R9FklJUHn16FAbrMk6+qsf+ox1rZmCO778F6f1J5KwqYzdMobcqrufWUOtJCO+DCg9ZsnWDA+/YxPtgZudmnaNQeXtm+V5dkQRxvRED1FY08ecvR3qvDlPoiFlpkT7C/zB3XbhF2TjWCheLRdF9E8aDG5UiCLdXGtEpeFyZv0xJZhc48qRDGP0/IwHoRddW/T0v/rr6nXL8NXPsgVJpSjy/netqgLkHO0L0oJbf5nQxcPW7olnn2GNbsL8BExO1lJdhP6xtX5yalFEnm1LqTqsOB23Yggp/XvML8Mkxurvn2D27nzFMbjV8F7QHFT4xl2nphlFyJ8qTgP4ZiHYygK60XWejYYrASN9jbAwaZ1UN3S5Sk5/gcNexR2qOlHkoHaBqD58t6rQwxy23HEfSoMOvOnWXfAu4/p7o5A6mvH9J0wwZP3v6vMoUhTjZZkNXaV61xTC5M1rK8ahRV17oNiLKLLpSo6UHByvoHWq/ytvCI6KLY8ic2zSahlw+Vj/xH+w3UzuaR/UXEvdJlkRRV6wPOqVh9Pug/FacO0BWmYXF40EiKYmf4EbrudGz0JTvpbje7hpZKKGWd0Xhs2l7AqDPS2y2+Khd6mpXbM0jfBHOLn3QjPeCP8J2NEbdltChkZOayQ228A1mZs+ucGHZU9Hz8JrrEcnTQ1opDL8L+cxyNxdoOgBfQYma+9A+vN0Pd2w6rbw6jG4JUdvyzxcb/5sq4Yz5vkRetIIfoyyumMNt906wZ8Pj55SsljjQiOhFTnJ3DCXTbpVFBbpldZqutOIS/PQWhO4zXKDkQ00tT7WVgA9z+quZ/agkdkx/iN88IDN3FVJKLbey3ivF43kpy8kHISCovEddvC/09xnnsH7ZmsblmHkDzlOVm8amUlxsBCEXx9sPWxxhkbeaYtkOEL3z+JDPnB835hRKTxVpeU5A+kzXhSu8qWRgcC9K+xQwt7VKyKbhv+/82AKDDh02vIOjFiwzpiAJL3bc/N9GlHoOj6wC/4ym7bQgTt2MaQHPaAR6dyjnDQoZl8WeQWW+jBZTMHTgTkPlR7SyLnZ6xK6UD4vK+MwjLPiv6NZTiMCrFu2mcALrNpPbeAjAan2VOhZGBL8GVpV8TJ+gyXCxXG/oX1LUHXoKI2kaOR5xUNN4UmBLNgz484/B61TKzy1vtBIzXQyvym0q/CrsoURxod9ksZphDNuSfgWXNR/1JgP6Rcn5BfhlQc6ajoTNKKccvGrGeybq02zg0PrqnJ7rkcTBovKnxPw5Osmtd8wlDH8iEpWNNl9bdTPH7p7upVRoL/zIn0KHKSFr0zciibjr1cb/IZK0rFJLLejidBpzZf6sHPn+1EKFBBulU+B8soDF+7A6Qw751dd0aR8hnWgGWrlvrHpgyZ8clWy3dHkz7PwR+6wyuS1dBAcNOC8R4O1Eiu/mnqjSVC7jG8vHJ84+WMSqpp+HJf5HE2k5haHXeF0bp7jOcje4DUYCWULQgJVB7Evo4u/DWD1wdhgKziVYRSRBo3GM+PbYVGxBPcwHPxenPIT3r7OGt00Fk0c7TK4e+GnZJWMSSg6uKtcZjyalFweHHCFdo0L7ueg1cVNvyKhTF2BXPM31N8sefEZmk416U/BgPqcc7JT0YRJveu2O9xZ6iIXBB/l0ZfRYNvLwY1ub2JI6Rlep0BoGmieS4PVJz34PkEJgULlTTUxeCeEh8rC9H77OnXoUmk/5/cthvxe23mCCnOabJpS4cPcv+c7Yaxlq7TgVAwR8OlKlYbOTNOr1WD+aTWxr8KXSaixfckC/Pwh5cBakctEu20x1wh+Z9P+FQuPvlyMyYJ/N1VK5MMMEjp8+F4seWTb2HUSstZLNZ+FM3ka9yrgwzMd55myY4lIRbWPILx9rNplG9y3L+zimaexREXvThgFMuR0hKdBnT86sZ+hLvVxwpbCWCJ/+GyyCiy/ZJK2HwYaG/DO+MeRnWbetWsC4siquPsX+OF4w25TB8gu0COUBy865bdWwN6J5MhWuOc9ZZN1bRzhCKne5AnzX68Xugh761hEGuA1ITZR/ro4ovbyt6gMDJtdFtOAMWE8H8VXx5O1nX/ZlGAQwx9tQ9iZvco4B4q5HhGbg1W8zEfW0sUT/Yz6y5vgoqLuaoP18cSoctLABtaoZyd4QaE4rYIXkPObajMzXzz51ZvCvwkOVqy2l4N/f7J5XNaNJ7MnHvXdgAvzJ8yfQpXBka2r9eKJTm3grCnMrn/v7gAXZlX7/WHCHefZZ2sSSLf7Q9ZX0KB0UaweSu3gTFqGkvlXRiUZEghNX3dlB0xzWeZRhRvYdUKf30sgvgYbdr6BpGm5rxk2v6Y3Y8hOIKoGbqw7oW3JkxdqkOLL6KkLN36PFT2Uk0DGxz612cLrCrsjXaCDx7J5Eky5sVr8JbxXUNTxFopwBdBa4f0oDlGG5gSyoP56ngOu9Q5r3gBbxIZ26MH69rw4HzjrV+98Abok/9CMhJ8kVO9c6UggrWcMw27DMn0nuzzI9lHl40c4xUEOrPmAdpml2zmgXoEG2wbo9HBxUyh/Igl02rAnBkbP6VqnwfpS+9YqqK3mvH8aFnj/dF2CD0JiIhkEEskbQc2Kx3qJZNvDaNaXsPbg4JFaSK3Mp81CTUGbF+L6icQqjI95B1T722OuCqc+3ZvqtE0kJ5Oemg3BpKDGJ1PQf93NPZuOJRKlpZRqQ3jgLvdWC/goNINmD++9mv/C55lI/s4xWovD8jNi9dthj8BynA2cd285RIPD1gerU2BjXI/iTRizTeqJ1TWM2zZq5gS9lwumvaHQE2OPLHjepGWkEboy0VM/wuC9RHIYxvh9Uu+qTyS09krWEdg5+7T7OzyydoZPtCGR3BJ1MjsAT3O+ErGBMlVbp51hxqrrGeekk8itVIU6CjR0b59LgElqH/IqodzXPscZeHZ5OvEPZDzI9opFJon8pq0qnz2SRBLXBGygs0oizSvzAezwvw8XxrSgtmGHlQ+0KX37LBi++a+GOxruV6sKm6hMImV3Jw0X4HsRSW6GqiTS+5SySwXe4Nln5AFpW3/wnIO1xg97KNAkhF42YU8y3knGPtfhS9G7RQ/guGp0Yx9886qyl1c9mcQlpkiIwwMi/m5ysCTRc9arIZnouD59fwHSGphzo2FM17RgFbz9foyyCHllquyZGpPJOq4c9fVwxfGhMZ1cCnnfRJ/ICXdaeXQIwy+1N78cgVJlMfMJUM/7vPoNWLs3KCwPxkXzGqwKTyHejztH2GHj2QfhQvDdkyfpznBo4zeuW7BZzLYgH0rXdpuWQ0YH9y6zaymkiIgm2MHAwRE9L/h37TXxHFjiULM4BPmHBR/PQHfpYNfVGSlkwYcWQJVOJXKSj9+mwISzYwJ34TVun+MDsJH5wV1hmVQyxHJubjtcn29poAHXsEh3hymkEll9HsVEeGsXe8JNePDVzeVeaBUi7rZxVyp5efVptQw87mghqgZ/sj95vv8A+nd9230UtlxUy3eDOmXr0+9DnpCSsBFYO5G5/AtuU046u8YslVDC3k9ZR6eSY7kJOW5wgsvBKRBKzR42K4Gx2h3q83DwhfYCY0wqGfWpeMoHRXOcdr65kko8JroW2+F4sP3rYdg7sXVc4moqYVzHsOgIq/y3vvaFeXI2seHQpkw2nutoGtnZkSQnDveeZ32vAJWv3T/kDzcXd38ohmbWS2drYTNNVrALDnJqKC4OpJHwD7JeLINp5OG6nfc3QodGxzc+0OLV+twiyH7q08hbmHC5UKTrn7myJQUWV0hWm5NfFWxUeLyzHebbHu+TtbxCfv9VbfOFc2lmCVTo6HLe5Ap8dFJXdenJFcLapm3P9vQK8d14OFIYsr1zlXSBDnsaq/Jhh3r6eCVM3nCeux3mVklHnvh0lYSstDD6wwbpxIgo+D/qNu8X + + + + + + eJzdXXlcjln7fwqp0FjCKOW2hgZZ45U6ZDdmkK1sJ8NkJ8vwWo8WImsGKXIPrxEaW/b12Mky2ZVwuillGRQh4vfpTn7zzDya5/ne3nfez3v94/PBdc79nOVavtdydDqYaNvv3hGAj5gnvTHEx1YXyULGo2PGP0P42C2rtFw+yWuXkvunWPI8HRlH8htctiXAJ/odfajOezvK8LzjN91CvufjdzXIUfeHz16SYGgc+Zh1JjI+21IlPpePdc65kfsnXUNTjRlHzC/7AJmPxxXSIeubT+TluYvIvCym33uIz/bsa4SPLnkBnT8SuxNaV1Ix4i7EdzNMQfjo80hIXvD+NkkQ3+mpmFzImH4D4ROhXikIH3UKv4LwSRcPQesimrdPQ/h4t3NXET55b4ObCB/JKqvuA79cC5JTutBpqj4hul/UfSHFvCE5zfy7q98v3r2C9imfeLs6dlrkmDT2ZnLu/GTyqsKaxqn8xCqXn9gUf0U0jJNPxO6gKp+lNHfj1md/Pej85RO74avOJ5ziriHjkCUXIL1Kl201Ss/9kXjr9DvQfIcjse8MuHMd4nsyVZO98b9C1H5iCUhOjKg4RMu9RIluuvOcaBmgZ2xb6Pc6zSuiSQ69/bXH37Fe4vuzTwnAR0d5CoQvn0hkkpum3+vQALIP2YXvGmmat8ctyE7MJ1F9bKXPsc/8aQfJmHFEwjjVHmZxocU+x7zSqXRV37JDtc+R3/09cWiiaV3+3UTcRg74HL9fXtm2nzrOQcuu/9H7uqVEu8/y/b7zuiPjkCsJkFz80/x33SB9QlOm3yfIfAu+0iZnjCSycX4z1Y4c2gjyez6OE1Lv85yrRUUycr+Dxx+xV+3DxBk1NI07Z1JVLfzCvRGEA+QTf76gnjr/j92ztYzz2WiJjctn2aedK77UhOd0jYP8MD5+IWSHf+Q3j3dU9cCZVZAf+afxFo0pcF+lSk1KqfNYbvhC03rZz8woaJ5PEd95CNJvvOZOCCdgWd820LSu765a/p6f9S33BPkOuvH0Q4SP+d74FZrvyApNdmU+8bvZen4fs9ihSX59iuiA8LfkL//X/5M0arZqt8ruYcUhPWx2yiB+bSzRmPrVtKyDfLGqirvofA9Y/34cyaYXhJ+Id79AfpNsduJx7nxSVD8z6Pesc4HkgBg70SB+J6V6mmRf8xtnVLkg/Heo9oJ4MBvD9QoXzzsPl2/+hvATZxsM3w2Yq+oduZPXC4Rf+iYtUeXb/oOS+6c0Yz5k33G/GAjXlmsuvVcQH9uyT/0+smg7Jo9a3MXwxDcrkk3h40GN6hvlB15pDp13cn9mgev0R2J9dRAuKDrtMukcSi7mKm5Bo4OgeI/8Kg06b7RwB5PsAPZtkJL7/+W47Qoyn65rmZxcPtow3SAeSWa6mmuS53eqQvioiEu6pH7XRMzfkU9mXEL4dM/8sfjJtFPQfkvzykByWVyaCuHxknNZyE4jI3cZtDOlKyGXc/9eOrlKjRPwkDST7JV8otFjID2hc90A5THoynHoXos597F1n3ndJDmXT9QiRsnlEz19FISfXzuI2eVXflXjnWJQJoTfit4yptemPcTiAdsOQXEu4TMe+k4e3wE7P+nhJunfj/MNrZgnB6vaqfdESm2F+X11nKD7yV/4q3YQn5kF2UP/c/R8leoXkDbZ/pr8viremuLcf0VS6tj+f0fc509Uvw10z+R7IyB5ixJZ7uzxX7FenyAWPPM2Afh49asKwpdP8okS5bSsC0ucn4jMz66/g34vE6lY/K5eAyjPR3a3xeT60UzI7qGnxikQX69kVW6x6xZYPprt8JKqnVeqOpYnZjdStZPZi0OlkfPEk74rEF9iPkEVoHGr7lfXgzQuDeU/ko5LH+Xy87njoXVh07sVOC+52rkQ8l3SndsQfiIydiq5fBIpDf2ej2Q2r0rud8uHT6t+IHPfqndPWIenmvBCOng2ZFeL9dmQPJKjbbC8pGF7sDyyd8FQXF1aGYaty9N4CO8kGXFq/EQcHV2gPOM+Pyu5/06sA6D7jxIrb6Pm7chbbhmFZ31ynBbOKl5iKnG/SCz/u5Qt5GfoEh7r7QPPvl5GE46zv5CFpnsaWDcPP24doAlP+m8jcTfSS/UDvEKg9SHXzBSCTFyoM4SL8d/qYXmc546r8RCd13jMf4znUN4cH+EIxZGZW1sIj9ZKbKH/V5ruGf8Buh986TpVvtASrnp4mLzluSb/SUxJeYnws4w0KI4o0cFKLh853NYoecm2FoXqHHSFv1LzRdi6Ztrsm08QOd9QW15QoSSTzr0oHaz+DmnPhOq/n1dEhtpC39HBvKghPr7IBqrTETU7Qf6R7ot/QedIWHhB/p/sVgqym4hFDiSnRIcTkF3AWyeZhHvzhLnqfpLQnyAchtZNyOMrtgOKO/K9tzA51GI2lNclt98A4dZsCrY+0uQUyJ+gSa5Y/MetuYrri5RvMLvyzmoobsI3b4NwA+EVheHsNq1NiqtxdlfP7mXBNaG4HIu0VxA+8c0ASH6wstWgfaTTnE2K78gxXyvIPCT9Z6heRXL009Ov7Exefos4EGywLvmviK8RUPyBLDqu5pnJ56Kg86DrNR3LAyDFMD30eAokv8jbZpi+HFgS0l/8RkUF4csnQsOMOgfk/BBM75hNg/BV3jlcT17xzHDo3PEm5TTFE/jMQZDfJGZuaKIpj3XpNcgPYQ286mryf34qB+VfsCHhat2LVONoHn9zH/Ue8GNV9fA6yd4Rs38epWrLQ+7PsProHEuj8jh55VQIl5T96kFyWFy3g/Doj/N2/hHSk3xBOQdo3lkdoTxQyfwUdF7YkxJ6OKrwuGeSfUhG2WP588tWQfKC2YdC+l3O+Nqkc81OWWmq0yBPi6t2K3Nv9wgZhzwpB+FmJKmGysfWM4N+8V9SUcXg/STH36s4FX3Szqi6QflEjEF7jzoOhfxr8n6iXt467VxbQcbJJ9n7kno/af/ymH8R4wbZL2xtV0ieSNMuqPORKRSSZ8z+mo36e8VdTbg2uxCAxYfCnSF8jgdZ6q/XEQHpAfnEcCjvioXdwfRO+woF3l9hV1iV12T7fKiuhNikYPlNF6Ow8xe5Ccsvt+sJ4Q28/iIMT39ljsX7rxTD5HTjh9B3kqIM2ge5xrrHEJ+1E2QXktar9X/fsglYXefUK9B3i8yH2Hy7YhVoPpJXv8O/WY/VccfVh3B+Ed8Ky8uuuhDLsxrpohjDR4JWYv2EfmqO9a3apsNw5s0OJtmTPHaSUesmm21U5R67FYT5e2+LQPKdt9kD5fdIfSKgeKKUwrH8tTeTIL1OIjZD9Ra65Wsgv0HuPAPDve9UgfSCSOuC5a3tGwDZx7JkB+2fztUCmk845OX7c9cv8/po7Vmg+pFSBSsFGs/8BnaO7LtB9qzUYxFW5/C04Ho21mUWVJfNJ++D/E3Jcaqm+nU6s5Wm/mOiyy2sDuLEA+w+nnusIHyy2ybMnhw7C8sPCDsH+Un8lA1kB4g3bSB9wR9VNu3+82Mm6TNp/H7FpPE/kLycQXpTDCkJyUER/x6rp/O9CX2nbtNrzI7/J9Z3SV44TVM/FtneVs3PYKmTsPoIVzuj+pXwiOEm2X908R6sfv3oVvWeyS93qXiiWLkZq98ufBaTD0VqYf7mq5VG9bv6I4l5QVaQnG+agcUT9/XD9OvBVX9LPhzfObGL3vpMi/gsfTDl+Dd19PpD/LgNyy8KmAidF+mRuWpXkff3INyQjugDfa/U6CGGm8WNh84bnTQMqvuRG0VaQvaLf7pRfj6nmRU1xeOCa0E4vri4QyEAHy/vCOHh5HCWNjt0k6z+TtpnGOb/942F8hDkkHPlNeHhI2Oxvsl209X8RHnhTqhfCe1ih8VR0/ub9L3k5i0I/yFLArF4pPdwzL5p0xP6Trr/ELSO9FhFLI5l76Gtb73ZESy/6fscqL6ev/4asovF+IWlNOWTLO6C5cO1DIXODy2ZgsX537aE+tZR205YHlN6UyxuHlGtpCY5l1kI62/yi58qzxkdXduY+aWcrjaQvosuo5c3wcaMgHAN6d5UqM6PbetiXxAfb1hR3Tfa/J0qF6m7HVb3FjcDsnNIvyQsX1ieBO2H7m5PKP9eKjwb69/lkg3FXWSHCKiOkG1YA62naOQNyUXecDIWZ1zwJbQPfG6qwd/HWjWGcC1hWxrLR1nZEXs/42ofdb2o2RO1DowuDMNw7vNt8uzR2m8xPEo3BcMnijhA/h5db5e3XmOSVFycliiMxZ/etNNbL3m4a15/vlpzsLi1+bdQv29pxiFVrssdWmH6+cXPWDzlbJ28e2ORV+dl8rwWV9R8XhKbgPX7cayByeu+myE8is9oh/WfbBmI5YsGVqsMycEIbz27kKbaQLgWfX0Zy5M+PQur1/F7Y/D8sn37sHcH1ocrCJ9oNRXiY563sXNc6ACEx8tOFxSET/d8E1b3t3srVr++txnmB/qEYPndW6lq59AJJRVoXnYdq/M4+hjSY6zpSaz+27EZludbpI6mOMd/itjV4/Tv7C8gTZzfAvIjetlj/Rm6V8Pk3IV49X7JpxoqCL888TmGC/VeCvX9EDHnsf69vyzB9O+ZuG6a8KR+DaH+/RLdpucHCP8wLE+mbwusLvS+pUm4HT99Det7NWEx9M6CtKsk1H9FtA0yzc9b9RDLA64ajPmvif5Y/WdQtILw8WeDTMLzyA+dsLrJbWshfJSdrKpA823ojunFSklYXXPvzZDfLllfMhgPknY00cNNqEsv7L3RTmUKjDfxeVOg38vqVMHquJP91PvHS5Yx6d5L7+tCeV/kHxehuCzpvQXTp519jNKHrF8DBRlf968Q6Fwzr2jMjs6ui+Unz/CH/IR8Yu5fQ3Y0n7wDe09x43rsd+7ZAMVvpFNHsXxnzzAMt/D+CXqXhMqG+0uRUdX18knZ4n9AOC/N3IH1T57lV7Dfm9UNwx9qPMP6vvhh/RTkjmug88p+PYz1A8w4nmdfOBnXz5vfToHit+RAC4hPd6CHnh/M1zlA+ygdKgXFDeU6PY3Cu/iMg5C+lytkm5T3xM1iVFyIdd+E1eFfn4D1jyh/AMoflq7PUxA+OicaevdPHiqaQnylXuS9UzeuIRbP9kzF6lMr+Wh7V8ydQ3mUn4tEpJXf58BV6O4o74LGoeGlsfyEp3VbQnKRW0LxE+aQiuVzfXUF8ufZoHRMrn4gsbMd1DeBsdlQnh0LCcXqLlaUg+QrrekM2RNsljmEu0mToyA7Tk4sCslzsqZo3rvvpwKx9zislmJ+QOVwyH6UnzJN9S+81F5V3onAS1i/J59oLA/cKQl6N094J2Lx6BZYHxRp9Cisbtw1GMpzlzyppv7/YklFa2hdz67G+rGvmIP1m71YG4vHjWyqIHzy4EUYfjpmRYHnjZ9ohp1jq6YmfQ91O63iOayPAsUjJfuiWJ7o+SRsfy97QHqbeW7G8qBHDYTqHeTpqyD5lU/c2sWgPyOsnaD+5+LEJuj35xM57FYP0iMvWYF5a+xYAtTflq3pqCmvXrKM8oTkUni5xlB+hkd0Q039tjo6VYf2fb8tlMfPe9lAeob5dso7956hkL6RhAeUV8mmW0FySFo4FMK/+IGu2PtovuUh/STfwvoQkDfuUD0ljVqO9QXaaI7FYZI9Mb/RwhPTB3POaup/x2OwdyalOYlQPi5PHQ317WceD7D9iEtWED45Zjl2TgPXYnGp6gEQ3qU7fAey2+jjwdC9kLq9LtDekQPy+v6TtRewfFzHxhAeTT1LQ/Ox+CMG7VeSPBDDnZdlYfGfD0RPVob0+Z++o/uFiZpwvu+6jyyw3sFhskI0jK+V6PMVXv/O/Cp+aTPUt5ZuCYbyfNieCFW+0eXJUF4SvVoW8sNp/WpY3cGgFMjvIS+KY3HZ/QGQXpUtE7F4tWU2Jh9tJxjUx7QrWidQ3uA6k8i5WJ5yli+U3yPbZUF8uqGzMJzRugr0+7ibce9fsGG7sLqg2MlY/tHmtVgdeoWVCjTfB6K6bKxOf29HCC+g+6OwPOuevbB+Eje7Qv4kvf8DFJ8lrb2xd+msumH13HE+WF1m8QVYXcyOmdB8UumXmD+Qud6gXGHvD0H2Pn8TBtXBkmAXSN6TJjsgPJl2dMP6+FUOguxLcbYGlu8zKgfLz3NvhPmVc19DOI94lojhb6lvFQLw8d0lsXyjgTeg8ym+eIbhOzubQH33Ps677xUW30nZYlSdLwk8i+XTN68C+cvkTpsC47qybgTWD2PcMqwv7D6wn2zdFlj8Net7zC8/E4v1tUgsjMWxElKwc3HMGoqj0z4e0P2Shg3F7GJyHcMlnbH6LurdE3sv8+q6Au0yujtYQcYVtWZrwknYTXsIJxF+a6G4Rz7JniegulZSvBdWH9+uPdZHpG4PyC6R36ZgfRbSBmD56pZHMRxh/lKM7+YAiE8K7YnZ0wlbMftpd2Ps/Szrdlh9bHRxrE6rz3YnyO7KWAr1q5fO74byCejGUZg+2TsAstPlOtsVhE+seITV96/E8tjp+joQPkBiN2DrWemSQb1HHiVAdpfk5IzhRJX+CcUTeciPGL4x/yoW3xn5UoH4XOpCfHxpANa/UiOJSlGjoXvtSjXlA8v2rbtCftXPvaH4AHeeDeH73PY0Fuebi/UFJk3aKwifbq+J9a0fSHZPrgnpkV5pUH4HL78cssfkgJGQfURvm2Hxi7etMH3epSikt8guHwXho6VTMfuBvMD06/4gbD3PhGD7PsxZzWOTHsyC8jR0EVtU/J9k1sL6wjXeh72f8KoDJG9YbAL27sKzHQWuLx03HMIFaVg0du9SzTH7YHxxKF7De8zH/IuhOzG+LhSqa5es9mF1A0mjsP6kTRygdyRovdoWkH5XJmDv/rlUwuoTfvPE6j4GJ2Nxju0lsLhQ7SdVoH3gDaD6G7GwMoR3yy83QHU79MVmbD2tt2N1wH6vsPwJ3y8x/Cu8O3Y+k0dA708zvhd7x6mlH3TfdVk5UN0VcSFYvbX1Q6xPypLFGK7TNxGrI2rRFetD7jkE0g90HPZ+kuT5BsIv5KlZWB+5QsOwPuQPn0L3QeddE3uPb2FnLK7knYLV+cadwPzFvdOx/NX7P0BygvUIwd6J6nQf2j/hYYbhTIGB2P7lzMbqqjw8sPj54HnQd7JH/grCRwbex+7f/HSsvr9/BUxOBC7C3n96XgY7L0FfYP0NXR9A38lreUH7QLxzsHN9viEWD/FdjeVpl/XD8l7GZCsIH+mfgdkFLk2xfRi3AqsbyVyC9fsklzA7MiJOQfjY0Qzo99FQrI8dS/PA+q9eNq3uNJ+ksb5YPVT9VlD/blo/G6tPuN/D9H34P/c9b3g= + + + + + + + + diff --git a/src/tests/class_tests/openms/executables.cmake b/src/tests/class_tests/openms/executables.cmake index 2f77dfeffae..f4dec7dbc28 100644 --- a/src/tests/class_tests/openms/executables.cmake +++ b/src/tests/class_tests/openms/executables.cmake @@ -68,6 +68,7 @@ set(datastructures_executables_list #MatrixUtils_test OPXLDataStructs_test Param_test + ParamValue_test QTCluster_test RangeManager_test StringListUtils_test @@ -633,6 +634,11 @@ set(transformations_executables_list ) endif(NOT DISABLE_OPENSWATH) +set(ionmobility_executables_list + FAIMSHelper_test + MSRunIMSplitter_test +) + set(simulation_executables_list DetectabilitySimulation_test DigestSimulation_test @@ -724,6 +730,7 @@ set(TEST_executables ${analysis_executables_list} ${applications_executables_list} ${transformations_executables_list} + ${ionmobility_executables_list} ${simulation_executables_list} ${swath_executables_list} ${qc_executables_list} diff --git a/src/tests/class_tests/openms/source/AccurateMassSearchEngine_test.cpp b/src/tests/class_tests/openms/source/AccurateMassSearchEngine_test.cpp index 4d9d46708b9..a305a65760d 100644 --- a/src/tests/class_tests/openms/source/AccurateMassSearchEngine_test.cpp +++ b/src/tests/class_tests/openms/source/AccurateMassSearchEngine_test.cpp @@ -104,8 +104,8 @@ START_SECTION([EXTRA]AdductInfo) END_SECTION Param ams_param; -ams_param.setValue("db:mapping", ListUtils::create(String(OPENMS_GET_TEST_DATA_PATH("reducedHMDBMapping.tsv")))); -ams_param.setValue("db:struct", ListUtils::create(String(OPENMS_GET_TEST_DATA_PATH("reducedHMDB2StructMapping.tsv")))); +ams_param.setValue("db:mapping", std::vector{OPENMS_GET_TEST_DATA_PATH("reducedHMDBMapping.tsv")}); +ams_param.setValue("db:struct", std::vector{OPENMS_GET_TEST_DATA_PATH("reducedHMDB2StructMapping.tsv")}); ams_param.setValue("keep_unidentified_masses", "true"); ams_param.setValue("mzTab:exportIsotopeIntensities", "true"); AccurateMassSearchEngine ams; @@ -375,8 +375,8 @@ START_SECTION([EXTRA] template void resolveAutoMode_(const MA MzTab mzt; Param p; p.setValue("ionization_mode","auto"); - p.setValue("db:mapping", ListUtils::create(String(OPENMS_GET_TEST_DATA_PATH("reducedHMDBMapping.tsv")))); - p.setValue("db:struct", ListUtils::create(String(OPENMS_GET_TEST_DATA_PATH("reducedHMDB2StructMapping.tsv")))); + p.setValue("db:mapping", std::vector{OPENMS_GET_TEST_DATA_PATH("reducedHMDBMapping.tsv")}); + p.setValue("db:struct", std::vector{OPENMS_GET_TEST_DATA_PATH("reducedHMDB2StructMapping.tsv")}); ams.setParameters(p); ams.init(); diff --git a/src/tests/class_tests/openms/source/DataValue_test.cpp b/src/tests/class_tests/openms/source/DataValue_test.cpp index 46a1dd32f65..d86579ff332 100644 --- a/src/tests/class_tests/openms/source/DataValue_test.cpp +++ b/src/tests/class_tests/openms/source/DataValue_test.cpp @@ -705,9 +705,9 @@ START_SECTION((String toString(bool full_precision) const)) TEST_EQUAL(a.toString(), "[test string, string2, last string]") a = DataValue(ListUtils::create("1,2,3,4,5")); TEST_EQUAL(a.toString(),"[1, 2, 3, 4, 5]") - a = DataValue(ListUtils::create("1.2,47.11")); - TEST_EQUAL(a.toString(),"[1.2, 47.109999999999999]") - TEST_EQUAL(a.toString(false), "[1.2, 47.11]") + a = DataValue(ListUtils::create("1.2,47.11,1.2345678e05")); + TEST_EQUAL(a.toString(),"[1.2, 47.109999999999999, 1.2345678e05]") + TEST_EQUAL(a.toString(false), "[1.2, 47.11, 1.235e05]") END_SECTION START_SECTION((bool toBool() const)) diff --git a/src/tests/class_tests/openms/source/FAIMSHelper_test.cpp b/src/tests/class_tests/openms/source/FAIMSHelper_test.cpp new file mode 100644 index 00000000000..ae63497fca5 --- /dev/null +++ b/src/tests/class_tests/openms/source/FAIMSHelper_test.cpp @@ -0,0 +1,90 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: Eugen Netz $ +// $Authors: Eugen Netz $ +// -------------------------------------------------------------------------- +// + +#include +#include + +/////////////////////////// + +#include +#include +#include + +using namespace OpenMS; +using namespace std; + +/////////////////////////// + +START_TEST(FAIMSHelper, "$Id$") + +///////////////////////////////////////////////////////////// + +FAIMSHelper* e_ptr = nullptr; +FAIMSHelper* e_nullPointer = nullptr; + +START_SECTION((FAIMSHelper())) + e_ptr = new FAIMSHelper; + TEST_NOT_EQUAL(e_ptr, e_nullPointer) +END_SECTION + +START_SECTION((~FAIMSHelper())) + delete e_ptr; +END_SECTION + +e_ptr = new FAIMSHelper(); + +START_SECTION((std::set getCompensationVoltages(PeakMap& exp))) + delete e_ptr; + e_ptr = new FAIMSHelper(); + MzMLFile IM_file; + PeakMap exp; + IM_file.load(OPENMS_GET_TEST_DATA_PATH("IM_FAIMS_test.mzML"), exp); + + TEST_EQUAL(exp.getSpectra().size(), 19) + + std::set CVs = e_ptr->getCompensationVoltages(exp); + + TEST_EQUAL(CVs.size(), 3) + TEST_EQUAL(CVs.find(-65.0) == CVs.end(), 0) + TEST_EQUAL(CVs.find(-55.0) == CVs.end(), 0) + TEST_EQUAL(CVs.find(-45.0) == CVs.end(), 0) + +END_SECTION + +delete e_ptr; + +///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////// +END_TEST diff --git a/src/tests/class_tests/openms/source/FIAMSDataProcessor_test.cpp b/src/tests/class_tests/openms/source/FIAMSDataProcessor_test.cpp index 827d74042aa..b1952e06ce0 100644 --- a/src/tests/class_tests/openms/source/FIAMSDataProcessor_test.cpp +++ b/src/tests/class_tests/openms/source/FIAMSDataProcessor_test.cpp @@ -80,10 +80,10 @@ p.setValue("resolution", 120000.0); p.setValue("polarity", "negative"); p.setValue("max_mz", 1500); p.setValue("bin_step", 20); -p.setValue("db:mapping", ListUtils::create(String(OPENMS_GET_TEST_DATA_PATH("reducedHMDBMapping.tsv")))); -p.setValue("db:struct", ListUtils::create(String(OPENMS_GET_TEST_DATA_PATH("reducedHMDB2StructMapping.tsv")))); -p.setValue("positive_adducts", String(OPENMS_GET_TEST_DATA_PATH("FIAMS_negative_adducts.tsv"))); -p.setValue("negative_adducts", String(OPENMS_GET_TEST_DATA_PATH("FIAMS_positive_adducts.tsv"))); +p.setValue("db:mapping", std::vector{OPENMS_GET_TEST_DATA_PATH("reducedHMDBMapping.tsv")}); +p.setValue("db:struct", std::vector{OPENMS_GET_TEST_DATA_PATH("reducedHMDB2StructMapping.tsv")}); +p.setValue("positive_adducts", OPENMS_GET_TEST_DATA_PATH("FIAMS_negative_adducts.tsv")); +p.setValue("negative_adducts", OPENMS_GET_TEST_DATA_PATH("FIAMS_positive_adducts.tsv")); fia_processor.setParameters(p); MSExperiment exp; diff --git a/src/tests/class_tests/openms/source/FeatureDeconvolution_test.cpp b/src/tests/class_tests/openms/source/FeatureDeconvolution_test.cpp index 10971e2ecf3..abba5e51d87 100644 --- a/src/tests/class_tests/openms/source/FeatureDeconvolution_test.cpp +++ b/src/tests/class_tests/openms/source/FeatureDeconvolution_test.cpp @@ -101,7 +101,7 @@ START_SECTION([EXTRA](void updateMembers_())) p.setValue("charge_max", 13, "maximal possible charge"); p.setValue("retention_max_diff", 1.0, "maximum allowed RT difference between any two features if their relation shall be determined"); p.setValue("retention_max_diff_local", 2.0, "maxi"); - p.setValue("potential_adducts", ListUtils::create("H:+:0.7,Na:+:0.1,(2)H4H-4:0:0.1:-2:heavy"), "Ad"); + p.setValue("potential_adducts", std::vector{"H:+:0.7","Na:+:0.1","(2)H4H-4:0:0.1:-2:heavy"}, "Ad"); fdt.setParameters(p); { @@ -141,7 +141,7 @@ START_SECTION([EXTRA](void updateMembers_())) p.setValue("charge_min", 11, "minimal possible charge"); p.setValue("charge_max", 13, "maximal possible charge"); p.setValue("q_try", "heuristic", "Try dif"); - p.setValue("potential_adducts", ListUtils::create("H:+:0.9,Na:++:0.1")); + p.setValue("potential_adducts", std::vector{"H:+:0.9","Na:++:0.1"}); p.setValue("retention_max_diff", 1.0, "maximum "); p.setValue("retention_max_diff_local", 1.0, "maxim"); p.setValue("intensity_filter", "true", "Enable"); @@ -214,7 +214,7 @@ START_SECTION(void compute(const FeatureMapType &fm_in, FeatureMapType &fm_out, FeatureDeconvolution fd; Param p; - p.setValue("potential_adducts", ListUtils::create("H:+:0.7,Na:+:0.1,(2)H4H-4:0:0.1:-2:heavy"), "Ad"); + p.setValue("potential_adducts", std::vector{"H:+:0.7","Na:+:0.1","(2)H4H-4:0:0.1:-2:heavy"}, "Ad"); p.setValue("mass_max_diff", 0.1); fd.setParameters(p); diff --git a/src/tests/class_tests/openms/source/FeatureFinderAlgorithm_test.cpp b/src/tests/class_tests/openms/source/FeatureFinderAlgorithm_test.cpp index 16e81e23e80..3ddea484f6c 100644 --- a/src/tests/class_tests/openms/source/FeatureFinderAlgorithm_test.cpp +++ b/src/tests/class_tests/openms/source/FeatureFinderAlgorithm_test.cpp @@ -114,7 +114,7 @@ END_SECTION START_SECTION((virtual Param getDefaultParameters() const)) FFA ffa; - TEST_EQUAL(String(ffa.getDefaultParameters().getValue("bla")),"bluff") + TEST_EQUAL(String(ffa.getDefaultParameters().getValue("bla").toString()),"bluff") END_SECTION START_SECTION((void setData(const MapType& map, FeatureMap features, FeatureFinder& ff))) diff --git a/src/tests/class_tests/openms/source/FileHandler_test.cpp b/src/tests/class_tests/openms/source/FileHandler_test.cpp index 607c2fe1a30..64576e09c4f 100644 --- a/src/tests/class_tests/openms/source/FileHandler_test.cpp +++ b/src/tests/class_tests/openms/source/FileHandler_test.cpp @@ -172,6 +172,22 @@ START_SECTION((static String swapExtension(const String& filename, const FileTyp TEST_STRING_EQUAL(FileHandler::swapExtension("./filename", FileTypes::UNKNOWN), "./filename.unknown") END_SECTION +START_SECTION((FileTypes::Type FileHandler::getConsistentOutputfileType(const String& output_filename, const String& requested_type))) + TEST_EQUAL(FileHandler::getConsistentOutputfileType("", ""), FileTypes::UNKNOWN) + TEST_EQUAL(FileHandler::getConsistentOutputfileType("a.unknown", "weird"), FileTypes::UNKNOWN) + TEST_EQUAL(FileHandler::getConsistentOutputfileType("a.idXML", ""), FileTypes::IDXML) + TEST_EQUAL(FileHandler::getConsistentOutputfileType("/home/doe/file.txt", ""), FileTypes::TXT) + TEST_EQUAL(FileHandler::getConsistentOutputfileType("/home/doe/file.txt", "featureXML"), FileTypes::UNKNOWN) + TEST_EQUAL(FileHandler::getConsistentOutputfileType("/home/doe/file.mzML.gz", ""), FileTypes::MZML) // special extension, known to OpenMS + TEST_EQUAL(FileHandler::getConsistentOutputfileType("/home/doe/file.mzML.gz", "mzML"), FileTypes::MZML) // special extension, known to OpenMS + TEST_EQUAL(FileHandler::getConsistentOutputfileType("/home/doe/file.txt.tgz", ""), FileTypes::UNKNOWN) // not special to us... + TEST_EQUAL(FileHandler::getConsistentOutputfileType("/home/doe/file.unknown", "idxml"), FileTypes::IDXML) + TEST_EQUAL(FileHandler::getConsistentOutputfileType("/home.with.dot/file", "mzML"), FileTypes::MZML) + TEST_EQUAL(FileHandler::getConsistentOutputfileType("c:\\home.with.dot\\file", "mzML"), FileTypes::MZML) +END_SECTION + + + START_SECTION((template < class PeakType > bool loadExperiment(const String &filename, MSExperiment< PeakType > &exp, FileTypes::Type force_type=FileTypes::UNKNOWN, ProgressLogger::LogType log=ProgressLogger::NONE, const bool compute_hash=true))) FileHandler tmp; PeakMap exp; diff --git a/src/tests/class_tests/openms/source/IDFilter_test.cpp b/src/tests/class_tests/openms/source/IDFilter_test.cpp index a88ef40827d..d533e24a798 100644 --- a/src/tests/class_tests/openms/source/IDFilter_test.cpp +++ b/src/tests/class_tests/openms/source/IDFilter_test.cpp @@ -723,6 +723,34 @@ START_SECTION((static void removePeptidesWithMatchingModifications(vector& peptides, const String& regex))) +{ + vector peptides = global_peptides; + String re{"[BJXZ]"}; + + IDFilter::removePeptidesWithMatchingRegEx(peptides, re); + TEST_EQUAL(peptides == global_peptides, true); // no changes + + PeptideHit aaa_hit1; + aaa_hit1.setSequence(AASequence::fromString("BBBBB")); + PeptideHit aaa_hit2; + aaa_hit2.setSequence(AASequence::fromString("JJJJJ")); + PeptideHit aaa_hit3; + aaa_hit3.setSequence(AASequence::fromString("XXXXX")); + peptides[0].getHits().push_back(aaa_hit1); + peptides[0].getHits().push_back(aaa_hit2); + peptides[0].getHits().push_back(aaa_hit3); + + TEST_EQUAL(peptides == global_peptides, false); // added aaa peptides + TEST_EQUAL(peptides[0].getHits().size(), 14); + + IDFilter::removePeptidesWithMatchingRegEx(peptides, re); + /// aaa peptides should now be removed + TEST_EQUAL(peptides == global_peptides, true); + TEST_EQUAL(peptides[0].getHits().size(), 11); +} +END_SECTION + START_SECTION((static void keepPeptidesWithMatchingModifications(vector& peptides, const set& modifications))) { vector peptides = global_peptides; diff --git a/src/tests/class_tests/openms/source/ITRAQLabeler_test.cpp b/src/tests/class_tests/openms/source/ITRAQLabeler_test.cpp index 32f855ac6d7..2a9f7b3d92b 100644 --- a/src/tests/class_tests/openms/source/ITRAQLabeler_test.cpp +++ b/src/tests/class_tests/openms/source/ITRAQLabeler_test.cpp @@ -87,7 +87,7 @@ START_SECTION((void setUpHook(SimTypes::FeatureMapSimVector &))) // add another map Param p = i.getParameters(); - p.setValue("channel_active_4plex", ListUtils::create("114:myReference, 117:blabla"), "Four-plex only: Each channel that was used in the experiment and its description (114-117) in format :, e.g. \"114:myref\",\"115:liver\"."); + p.setValue("channel_active_4plex", std::vector{"114:myReference"," 117:blabla"}, "Four-plex only: Each channel that was used in the experiment and its description (114-117) in format :, e.g. \"114:myref\",\"115:liver\"."); i.setParameters(p); f_maps.push_back(FeatureMap()); i.setUpHook(f_maps); @@ -234,9 +234,9 @@ START_SECTION((void postRawTandemMSHook(SimTypes::FeatureMapSimVector &, SimType Param p; p = i.getParameters(); // no isotope skewing - StringList iso = ListUtils::create("114:0/0/100/0,115:0/0/0/0,116:0/0/0/0,117:0/100/0/0"); + std::vector iso = {"114:0/0/100/0","115:0/0/0/0","116:0/0/0/0","117:0/100/0/0"}; p.setValue("isotope_correction_values_4plex", iso); - StringList ch = ListUtils::create("114:c1,115:c2,116:c3,117:c4"); + std::vector ch = {"114:c1","115:c2","116:c3","117:c4"}; p.setValue("channel_active_4plex", ch); p.setValue("iTRAQ", "4plex"); i.setParameters(p); @@ -254,16 +254,16 @@ START_SECTION((void postRawTandemMSHook(SimTypes::FeatureMapSimVector &, SimType exp=exp2;//revert // with isotope skewing - iso = ListUtils::create("113:0/0/100/0," - "114:0/0/50 /0," - "115:0/100/0/0," - "116:0/0/100/0," - "117:0/0/0/100," - "118:0/0/100/0," - "119:0/0/100/0," - "121:0/100/0/0"); + iso = {"113:0/0/100/0", + "114:0/0/50 /0", + "115:0/100/0/0", + "116:0/0/100/0", + "117:0/0/0/100", + "118:0/0/100/0", + "119:0/0/100/0", + "121:0/100/0/0"}; p.setValue("isotope_correction_values_8plex", iso); - ch = ListUtils::create("113:ch0,114:c1,115:c2,116:c3,117:c4,118:c5,119:c6,121:c7"); + ch = {"113:ch0","114:c1","115:c2","116:c3","117:c4","118:c5","119:c6","121:c7"}; p.setValue("channel_active_8plex", ch); p.setValue("iTRAQ", "8plex"); i.setParameters(p); diff --git a/src/tests/class_tests/openms/source/IdentificationDataConverter_test.cpp b/src/tests/class_tests/openms/source/IdentificationDataConverter_test.cpp index 122c2b68f72..ac4b7e16f31 100644 --- a/src/tests/class_tests/openms/source/IdentificationDataConverter_test.cpp +++ b/src/tests/class_tests/openms/source/IdentificationDataConverter_test.cpp @@ -123,7 +123,7 @@ END_SECTION START_SECTION((void importSequences(IdentificationData&, const vector&, IdentificationData::MoleculeType, const String&))) { vector fasta; - FASTAFile::load(OPENMS_GET_TEST_DATA_PATH("FASTAFile_test.fasta"), fasta); + FASTAFile().load(OPENMS_GET_TEST_DATA_PATH("FASTAFile_test.fasta"), fasta); IdentificationData ids; IdentificationDataConverter::importSequences(ids, fasta); TEST_EQUAL(ids.getParentMolecules().size(), 5); diff --git a/src/tests/class_tests/openms/source/IonizationSimulation_test.cpp b/src/tests/class_tests/openms/source/IonizationSimulation_test.cpp index 9e8e29cc735..d8af0ba1c5c 100644 --- a/src/tests/class_tests/openms/source/IonizationSimulation_test.cpp +++ b/src/tests/class_tests/openms/source/IonizationSimulation_test.cpp @@ -117,9 +117,9 @@ START_SECTION((void ionize(SimTypes::FeatureMapSim &features, ConsensusMap &char IonizationSimulation esi_sim(rnd_gen); Param esi_param = esi_sim.getParameters(); esi_param.setValue("ionization_type","ESI"); - esi_param.setValue("esi:ionized_residues",ListUtils::create("Arg,Lys,His")); + esi_param.setValue("esi:ionized_residues", std::vector{"Arg","Lys","His"}); esi_param.setValue("esi:ionization_probability", 0.8); - esi_param.setValue("esi:charge_impurity", ListUtils::create("H+:1,NH4+:0.2,Ca++:0.1")); + esi_param.setValue("esi:charge_impurity", std::vector{"H+:1","NH4+:0.2","Ca++:0.1"}); esi_param.setValue("esi:max_impurity_set_size", 3); esi_param.setValue("mz:upper_measurement_limit", 2500.0, "Upper m/z detector limit."); diff --git a/src/tests/class_tests/openms/source/LogConfigHandler_test.cpp b/src/tests/class_tests/openms/source/LogConfigHandler_test.cpp index 04a41d25dae..00f98781283 100644 --- a/src/tests/class_tests/openms/source/LogConfigHandler_test.cpp +++ b/src/tests/class_tests/openms/source/LogConfigHandler_test.cpp @@ -66,7 +66,7 @@ START_SECTION((Param parse(const StringList &setting))) Param p = LogConfigHandler::getInstance().parse(settings); // p should contain a list of the above set commands - StringList parsedConfigs = p.getValue(LogConfigHandler::PARAM_NAME); + std::vector parsedConfigs = p.getValue(LogConfigHandler::PARAM_NAME); TEST_EQUAL(parsedConfigs[0] , "DEBUG add cout FILE") TEST_EQUAL(parsedConfigs[1] , "DEBUG add a.out FILE") @@ -82,13 +82,12 @@ END_SECTION START_SECTION((void configure(const Param ¶m))) { - StringList settings; - settings.push_back("INFO add testing_info_warn_stream STRING"); - settings.push_back("WARNING add testing_info_warn_stream STRING"); - settings.push_back("ERROR add only_error_string_stream STRING"); - settings.push_back("INFO remove cout FILE"); - settings.push_back("WARNING remove cout"); - settings.push_back("ERROR remove cerr FILE"); + std::vector settings = {"INFO add testing_info_warn_stream STRING", + "WARNING add testing_info_warn_stream STRING", + "ERROR add only_error_string_stream STRING", + "INFO remove cout FILE", + "WARNING remove cout", + "ERROR remove cerr FILE"}; Param p; p.setValue(LogConfigHandler::PARAM_NAME, settings, "List of all settings that should be applied to the current Logging Configuration"); @@ -143,7 +142,7 @@ END_SECTION START_SECTION((ostream& getStream(const String &stream_name))) { - StringList settings; + std::vector settings; settings.push_back("INFO add testing_getStream STRING"); Param p; diff --git a/src/tests/class_tests/openms/source/MRMFeatureFinderScoring_test.cpp b/src/tests/class_tests/openms/source/MRMFeatureFinderScoring_test.cpp index f12aff59a2b..f951c8dd900 100644 --- a/src/tests/class_tests/openms/source/MRMFeatureFinderScoring_test.cpp +++ b/src/tests/class_tests/openms/source/MRMFeatureFinderScoring_test.cpp @@ -234,8 +234,8 @@ START_SECTION(void pickExperiment(OpenSwath::SpectrumAccessPtr input, FeatureMap MRMFeatureFinderScoring ff; Param ff_param = MRMFeatureFinderScoring().getDefaults(); Param scores_to_use; - scores_to_use.setValue("use_uis_scores", "true", "Use UIS scores for peptidoform identification ", ListUtils::create("advanced")); - scores_to_use.setValidStrings("use_uis_scores", ListUtils::create("true,false")); + scores_to_use.setValue("use_uis_scores", "true", "Use UIS scores for peptidoform identification ", {"advanced"}); + scores_to_use.setValidStrings("use_uis_scores", {"true","false"}); ff_param.insert("Scores:", scores_to_use); ff_param.setValue("TransitionGroupPicker:PeakPickerMRM:method", "legacy"); // old parameters ff_param.setValue("TransitionGroupPicker:PeakPickerMRM:peak_width", 40.0); // old parameters diff --git a/src/tests/class_tests/openms/source/MRMFragmentSelection_test.cpp b/src/tests/class_tests/openms/source/MRMFragmentSelection_test.cpp index b4a21f44f7d..72590704511 100644 --- a/src/tests/class_tests/openms/source/MRMFragmentSelection_test.cpp +++ b/src/tests/class_tests/openms/source/MRMFragmentSelection_test.cpp @@ -119,7 +119,7 @@ START_SECTION((void selectFragments(std::vector< Peak1D > &selected_peaks, const MRMFragmentSelection mrmfs; Param p(mrmfs.getParameters()); p.setValue("num_top_peaks", 1); - p.setValue("allowed_ion_types", ListUtils::create("y")); + p.setValue("allowed_ion_types", std::vector{"y"}); mrmfs.setParameters(p); vector selected_peaks; diff --git a/src/tests/class_tests/openms/source/MSExperiment_test.cpp b/src/tests/class_tests/openms/source/MSExperiment_test.cpp index f218e9b416e..bdbfe726128 100644 --- a/src/tests/class_tests/openms/source/MSExperiment_test.cpp +++ b/src/tests/class_tests/openms/source/MSExperiment_test.cpp @@ -94,7 +94,6 @@ START_SECTION((MSExperiment(const MSExperiment&& source))) #ifndef OPENMS_COMPILER_MSVC TEST_EQUAL(noexcept(MSExperiment(std::declval())), true) #endif - PeakMap tmp; tmp.getContacts().resize(1); tmp.getContacts()[0].setFirstName("Name"); diff --git a/src/tests/class_tests/openms/source/MSRunIMSplitter_test.cpp b/src/tests/class_tests/openms/source/MSRunIMSplitter_test.cpp new file mode 100644 index 00000000000..95e92c6989d --- /dev/null +++ b/src/tests/class_tests/openms/source/MSRunIMSplitter_test.cpp @@ -0,0 +1,106 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Maintainer: Eugen Netz $ +// $Authors: Eugen Netz $ +// -------------------------------------------------------------------------- +// + +#include +#include + +/////////////////////////// + +#include +#include +#include + +using namespace OpenMS; +using namespace std; + +/////////////////////////// + +START_TEST(MSRunIMSplitter, "$Id$") + +///////////////////////////////////////////////////////////// + +MSRunIMSplitter* e_ptr = nullptr; +MSRunIMSplitter* e_nullPointer = nullptr; + +START_SECTION((MSRunIMSplitter())) + e_ptr = new MSRunIMSplitter; + TEST_NOT_EQUAL(e_ptr, e_nullPointer) +END_SECTION + +START_SECTION((~MSRunIMSplitter())) + delete e_ptr; +END_SECTION + +e_ptr = new MSRunIMSplitter(); + +START_SECTION((std::vector splitByFAIMSCV(PeakMap& exp))) + delete e_ptr; + e_ptr = new MSRunIMSplitter(); + MzMLFile IM_file; + PeakMap exp; + IM_file.load(OPENMS_GET_TEST_DATA_PATH("IM_FAIMS_test.mzML"), exp); + + TEST_EQUAL(exp.getSpectra().size(), 19) + + vector splitPeakMap = e_ptr->splitByFAIMSCV(std::move(exp)); + TEST_EQUAL(splitPeakMap.size(), 3) + + TEST_EQUAL(splitPeakMap[0].size(), 4) + TEST_EQUAL(splitPeakMap[1].size(), 9) + TEST_EQUAL(splitPeakMap[2].size(), 6) + + for (PeakMap::Iterator it = splitPeakMap[0].begin(); it != splitPeakMap[0].end(); ++it) + { + TEST_EQUAL(it->getDriftTime(), -65.0) + } + for (PeakMap::Iterator it = splitPeakMap[1].begin(); it != splitPeakMap[1].end(); ++it) + { + TEST_EQUAL(it->getDriftTime(), -55.0) + } + for (PeakMap::Iterator it = splitPeakMap[2].begin(); it != splitPeakMap[2].end(); ++it) + { + TEST_EQUAL(it->getDriftTime(), -45.0) + } + + TEST_EQUAL(splitPeakMap[1].getExperimentalSettings().getDateTime().toString(), "2019-09-07T09:40:04") + +END_SECTION + + +delete e_ptr; + +///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////// +END_TEST diff --git a/src/tests/class_tests/openms/source/MascotGenericFile_test.cpp b/src/tests/class_tests/openms/source/MascotGenericFile_test.cpp index 17106a4aeb3..66fcf0ce161 100644 --- a/src/tests/class_tests/openms/source/MascotGenericFile_test.cpp +++ b/src/tests/class_tests/openms/source/MascotGenericFile_test.cpp @@ -85,8 +85,8 @@ START_SECTION((void store(std::ostream &os, const String &filename, const PeakMa // handling of modifications: Param params = ptr->getParameters(); - params.setValue("fixed_modifications", ListUtils::create("Carbamidomethyl (C),Phospho (S)")); - params.setValue("variable_modifications", ListUtils::create("Oxidation (M),Deamidated (N),Deamidated (Q)")); + params.setValue("fixed_modifications", std::vector{"Carbamidomethyl (C)","Phospho (S)"}); + params.setValue("variable_modifications", std::vector{"Oxidation (M)","Deamidated (N)","Deamidated (Q)"}); ptr->setParameters(params); stringstream ss; diff --git a/src/tests/class_tests/openms/source/MetaboliteFeatureDeconvolution_test.cpp b/src/tests/class_tests/openms/source/MetaboliteFeatureDeconvolution_test.cpp index 6d5c8657d13..fde4b90b7b4 100644 --- a/src/tests/class_tests/openms/source/MetaboliteFeatureDeconvolution_test.cpp +++ b/src/tests/class_tests/openms/source/MetaboliteFeatureDeconvolution_test.cpp @@ -101,7 +101,7 @@ START_SECTION([EXTRA](void updateMembers_())) p.setValue("charge_max", 13, "maximal possible charge"); p.setValue("retention_max_diff", 1.0, "maximum allowed RT difference between any two features if their relation shall be determined"); p.setValue("retention_max_diff_local", 2.0, "maxi"); - p.setValue("potential_adducts", ListUtils::create("H:+:0.7,Na:+:0.3,(2)H4H-4:0:0.2:-2:heavy"), "Ad"); + p.setValue("potential_adducts", std::vector{"H:+:0.7","Na:+:0.3","(2)H4H-4:0:0.2:-2:heavy"}, "Ad"); fdt.setParameters(p); { @@ -141,7 +141,7 @@ START_SECTION([EXTRA](void updateMembers_())) p.setValue("charge_min", 11, "minimal possible charge"); p.setValue("charge_max", 13, "maximal possible charge"); p.setValue("q_try", "heuristic", "Try dif"); - p.setValue("potential_adducts", ListUtils::create("H:+:0.9,Na:++:0.1")); + p.setValue("potential_adducts", std::vector{"H:+:0.9","Na:++:0.1"}); p.setValue("retention_max_diff", 1.0, "maximum "); p.setValue("retention_max_diff_local", 1.0, "maxim"); p.setValue("intensity_filter", "true", "Enable"); @@ -214,7 +214,7 @@ START_SECTION(void compute(const FeatureMapType &fm_in, FeatureMapType &fm_out, MetaboliteFeatureDeconvolution fd; Param p; - p.setValue("potential_adducts", ListUtils::create("H:+:0.7,Na:+:0.3,(2)H4H-4:0:0.2:-2:heavy"), "Ad"); + p.setValue("potential_adducts", std::vector{"H:+:0.7","Na:+:0.3","(2)H4H-4:0:0.2:-2:heavy"}, "Ad"); p.setValue("mass_max_diff", 0.1); p.setValue("use_minority_bound","true","enable bound"); fd.setParameters(p); @@ -236,7 +236,7 @@ START_SECTION(void compute(const FeatureMapType &fm_in, FeatureMapType &fm_out, //small pos test file with specific ions Param p_pos; - p_pos.setValue("potential_adducts", ListUtils::create("H:+:0.6,Na:+:0.2,NH4:+:0.1,K:+:0.1,C2H3N:0:0.05,H-2O-1:0:0.05,H-1Na:0:0.05"), "Ad_p"); + p_pos.setValue("potential_adducts", std::vector{"H:+:0.6","Na:+:0.2","NH4:+:0.1","K:+:0.1","C2H3N:0:0.05","H-2O-1:0:0.05","H-1Na:0:0.05"}, "Ad_p"); p_pos.setValue("charge_min", 1, "minimal possible charge"); p_pos.setValue("charge_max", 3, "maximal possible charge"); p_pos.setValue("charge_span_max", 3); @@ -267,7 +267,7 @@ START_SECTION(void compute(const FeatureMapType &fm_in, FeatureMapType &fm_out, //small neg test file with specific ions Param p_neg; - p_neg.setValue("potential_adducts", ListUtils::create("H-1:-:0.6,Cl:-:0.2,Br:-:0.2,CH2O2:0:0.05,H-2O-1:0:0.05,H-1Na:0:0.05,H-1K:0:0.05"), "Ad_n"); + p_neg.setValue("potential_adducts", std::vector{"H-1:-:0.6","Cl:-:0.2","Br:-:0.2","CH2O2:0:0.05","H-2O-1:0:0.05","H-1Na:0:0.05","H-1K:0:0.05"}, "Ad_n"); p_neg.setValue("charge_min", -3, "minimal possible charge"); p_neg.setValue("charge_max", -1, "maximal possible charge"); p_neg.setValue("charge_span_max", 3); @@ -299,7 +299,7 @@ START_SECTION(void compute(const FeatureMapType &fm_in, FeatureMapType &fm_out, //small pos test file with specific ions and ppm error Param p_pos_ppm; - p_pos_ppm.setValue("potential_adducts", ListUtils::create("H:+:0.6,Na:+:0.4"), "Ad_p"); + p_pos_ppm.setValue("potential_adducts", std::vector{"H:+:0.6","Na:+:0.4"}, "Ad_p"); p_pos_ppm.setValue("charge_min", 1, "minimal possible charge"); p_pos_ppm.setValue("charge_max", 3, "maximal possible charge"); p_pos_ppm.setValue("charge_span_max", 3); diff --git a/src/tests/class_tests/openms/source/O18Labeler_test.cpp b/src/tests/class_tests/openms/source/O18Labeler_test.cpp index e932066d714..cf871ebfa00 100644 --- a/src/tests/class_tests/openms/source/O18Labeler_test.cpp +++ b/src/tests/class_tests/openms/source/O18Labeler_test.cpp @@ -145,13 +145,13 @@ END_SECTION START_SECTION((void preCheck(Param ¶m) const )) { Param p; - p.setValue("Digestion:enzyme","Trypsin","Test Param", ListUtils::create("")); + p.setValue("Digestion:enzyme","Trypsin","Test Param", {}); O18Labeler labeler; labeler.preCheck(p); Param p_Exception; - p_Exception.setValue("Digestion:enzyme","not-Trypsin","Test Param", ListUtils::create("")); + p_Exception.setValue("Digestion:enzyme","not-Trypsin","Test Param",{}); TEST_EXCEPTION(Exception::InvalidParameter, labeler.preCheck(p_Exception)) } END_SECTION diff --git a/src/tests/class_tests/openms/source/OpenPepXLAlgorithm_test.cpp b/src/tests/class_tests/openms/source/OpenPepXLAlgorithm_test.cpp index cff08446104..72b11f7bcd3 100644 --- a/src/tests/class_tests/openms/source/OpenPepXLAlgorithm_test.cpp +++ b/src/tests/class_tests/openms/source/OpenPepXLAlgorithm_test.cpp @@ -96,7 +96,7 @@ PeakMap spectra; OpenPepXLAlgorithm search_algorithm; Param algo_param = search_algorithm.getParameters(); -algo_param.setValue("modifications:fixed", ListUtils::create("Carbamidomethyl (C)")); +algo_param.setValue("modifications:fixed", std::vector{"Carbamidomethyl (C)"}); algo_param.setValue("fragment:mass_tolerance", 0.2, "Fragment mass tolerance"); algo_param.setValue("fragment:mass_tolerance_xlinks", 0.3, "Fragment mass tolerance for cross-link ions"); algo_param.setValue("fragment:mass_tolerance_unit", "Da", "Unit of fragment m"); diff --git a/src/tests/class_tests/openms/source/OpenPepXLLFAlgorithm_test.cpp b/src/tests/class_tests/openms/source/OpenPepXLLFAlgorithm_test.cpp index d702aa48b2a..6bc329a0f04 100644 --- a/src/tests/class_tests/openms/source/OpenPepXLLFAlgorithm_test.cpp +++ b/src/tests/class_tests/openms/source/OpenPepXLLFAlgorithm_test.cpp @@ -89,7 +89,7 @@ PeakMap spectra; OpenPepXLLFAlgorithm search_algorithm; Param algo_param = search_algorithm.getParameters(); -algo_param.setValue("modifications:fixed", ListUtils::create("Carbamidomethyl (C)")); +algo_param.setValue("modifications:fixed", std::vector{"Carbamidomethyl (C)"}); search_algorithm.setParameters(algo_param); // run algorithm diff --git a/src/tests/class_tests/openms/source/ParamValue_test.cpp b/src/tests/class_tests/openms/source/ParamValue_test.cpp new file mode 100644 index 00000000000..f180f8f5067 --- /dev/null +++ b/src/tests/class_tests/openms/source/ParamValue_test.cpp @@ -0,0 +1,833 @@ +// -------------------------------------------------------------------------- +// OpenMS -- Open-Source Mass Spectrometry +// -------------------------------------------------------------------------- +// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, +// ETH Zurich, and Freie Universitaet Berlin 2002-2020. +// +// This software is released under a three-clause BSD license: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of any author or any participating institution +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// For a full list of authors, refer to the file AUTHORS. +// -------------------------------------------------------------------------- +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING +// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// -------------------------------------------------------------------------- +// $Authors: Ruben Grünberg $ +// -------------------------------------------------------------------------- + +#include + +/////////////////////////// +#include +/////////////////////////// + +#include +#include + +#include +#include + +// we ignore the -Wunused-value warning here, since we do not want the compiler +// to report problems like +// ParamValue_test.cpp:285:3: warning: expression result unused [-Wunused-value] +// TEST_EXCEPTION(Exception::ConversionError, (StringList)ParamValue("abc,ab")) + +#ifdef __clang__ +#pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunused-value" +#endif + +/////////////////////////// + +START_TEST(ParamValue, "$Id$") + +///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////// + + using namespace OpenMS; + using namespace std; + +// default ctor + ParamValue* dv_ptr = nullptr; + ParamValue* dv_nullPointer = nullptr; + START_SECTION((ParamValue())) + + // Just as a sanity check, the size of ParamValue should be exactly 16 bytes + // on a 64 bit system: + // - 1 byte for the data type + // - 7 byte padding + // - 8 bytes for the actual data / pointers to data + std::cout << "\n\n --- Size of ParamValue " << sizeof(ParamValue) << std::endl; + + dv_ptr = new ParamValue; + TEST_NOT_EQUAL(dv_ptr, dv_nullPointer) + END_SECTION + +// destructor + START_SECTION((virtual ~ParamValue())) + delete dv_ptr; + END_SECTION + +// ctor for all supported types a ParamValue object can hold + + START_SECTION((ParamValue(long double))) + long double x = -3.4L; + ParamValue d(x); + // Note: The implementation uses typedef double (as opposed to float, double, long double.) + TEST_REAL_SIMILAR((double)d, -3.4L) + END_SECTION + + START_SECTION((ParamValue(double))) + double x = -3.0; + ParamValue d(x); + // Note: The implementation uses typedef double (as opposed to float, double, long double.) + TEST_REAL_SIMILAR((double)d, -3.0); + END_SECTION + + START_SECTION((ParamValue(float))) + float x = 3.0; + ParamValue d(x); + // Note: The implementation uses typedef double (as opposed to float, double, long double.) + TEST_REAL_SIMILAR((double)d, 3.0); + END_SECTION + + + START_SECTION((ParamValue(short int))) + short int n = -3000; + ParamValue d(n); + TEST_EQUAL((short int)d, -3000) + END_SECTION + + START_SECTION((ParamValue(unsigned short int))) + unsigned short int n = 3000u; + ParamValue d(n); + TEST_EQUAL((unsigned short)d, 3000u) + END_SECTION + + START_SECTION((ParamValue(int))) + int n = -3000; + ParamValue d(n); + TEST_EQUAL((int)d, -3000) + END_SECTION + + START_SECTION((ParamValue(unsigned))) + unsigned int n = 3000u; + ParamValue d(n); + TEST_EQUAL((unsigned int)d, 3000u) + END_SECTION + + START_SECTION((ParamValue(long int))) + long int n = -3000; + ParamValue d(n); + TEST_EQUAL((long int)d, -3000) + END_SECTION + + START_SECTION((ParamValue(unsigned long))) + unsigned long int n = 3000u; + ParamValue d(n); + TEST_EQUAL((unsigned long int)d, 3000u) + END_SECTION + + START_SECTION((ParamValue(long long))) + long long n = -3000; + ParamValue d(n); + TEST_EQUAL((long long) d, -3000) + END_SECTION + + START_SECTION((ParamValue(unsigned long long))) + unsigned long long n = 3000; + ParamValue d(n); + TEST_EQUAL((unsigned long long) d, 3000) + END_SECTION + + START_SECTION((ParamValue(const char*))) + const char* s = "test char"; + ParamValue d(s); + TEST_EQUAL((std::string)d, "test char") + END_SECTION + + START_SECTION((ParamValue(const std::string&))) + string s = "test string"; + ParamValue d(s); + TEST_EQUAL(d, "test string") + END_SECTION + + START_SECTION((ParamValue(const vector &))) + vector sl = {"test string", "test String 2"}; + ParamValue d(sl); + TEST_EQUAL(d == sl, true) + END_SECTION + + START_SECTION((ParamValue(const vector &))) + vector il = {1, 2}; + ParamValue d(il); + TEST_EQUAL(d == il, true) + END_SECTION + + START_SECTION((ParamValue(const vector &))) + vector dl = {1.2, 22.3333}; + ParamValue d(dl); + //vector dldv = d; + TEST_EQUAL(d == dl, true); + END_SECTION + +// copy ctor + START_SECTION((ParamValue(const ParamValue&))) + { + ParamValue p1((double) 1.23); + ParamValue p3((float) 1.23); + ParamValue p4((Int) -3); + ParamValue p5((UInt) 123); + ParamValue p6("test char"); + ParamValue p7(std::string("test string")); + ParamValue p8({"test string","string2","last string"}); + ParamValue p9; + ParamValue p10(vector{1,2,3,4,5}); + ParamValue p11(vector{1.2,2.3,3.4}); + ParamValue copy_of_p1(p1); + ParamValue copy_of_p3(p3); + ParamValue copy_of_p4(p4); + ParamValue copy_of_p5(p5); + ParamValue copy_of_p6(p6); + ParamValue copy_of_p7(p7); + ParamValue copy_of_p8(p8); + ParamValue copy_of_p9(p9); + ParamValue copy_of_p10(p10); + ParamValue copy_of_p11(p11); + TEST_REAL_SIMILAR( (double) copy_of_p1, 1.23) + TEST_REAL_SIMILAR( (float) copy_of_p3, 1.23) + TEST_EQUAL( (Int) copy_of_p4, -3) + TEST_EQUAL( (UInt) copy_of_p5, 123) + TEST_EQUAL( (std::string) copy_of_p6, "test char") + TEST_EQUAL( (std::string) copy_of_p7, "test string") + TEST_EQUAL( copy_of_p8 == ListUtils::create("test string,string2,last string"), true) + TEST_EQUAL( (copy_of_p9.isEmpty()), true) + TEST_EQUAL( copy_of_p10 == ListUtils::create("1,2,3,4,5"), true) + TEST_EQUAL( copy_of_p11 == ListUtils::create("1.2,2.3,3.4"), true) + } + END_SECTION + +// move ctor + START_SECTION((ParamValue(ParamValue&&) noexcept)) + { + // Ensure that ParamValue has a no-except move constructor (otherwise + // std::vector is inefficient and will copy instead of move). + TEST_EQUAL(noexcept(ParamValue(std::declval())), true) + + ParamValue empty; + ParamValue p1((double) 1.23); + ParamValue p3((float) 1.23); + ParamValue p4((Int) -3); + ParamValue p5((UInt) 123); + ParamValue p6("test char"); + ParamValue p7(std::string("test string")); + ParamValue p8({"test string","string2","last string"}); + ParamValue p9; + ParamValue p10(vector{1,2,3,4,5}); + ParamValue p11(vector{1.2,2.3,3.4}); + ParamValue copy_of_p1(std::move(p1)); + ParamValue copy_of_p3(std::move(p3)); + ParamValue copy_of_p4(std::move(p4)); + ParamValue copy_of_p5(std::move(p5)); + ParamValue copy_of_p6(std::move(p6)); + ParamValue copy_of_p7(std::move(p7)); + ParamValue copy_of_p8(std::move(p8)); + ParamValue copy_of_p9(std::move(p9)); + ParamValue copy_of_p10(std::move(p10)); + ParamValue copy_of_p11(std::move(p11)); + TEST_REAL_SIMILAR( (double) copy_of_p1, 1.23) + TEST_REAL_SIMILAR( (float) copy_of_p3, 1.23) + TEST_EQUAL( (Int) copy_of_p4, -3) + TEST_EQUAL( (UInt) copy_of_p5, 123) + TEST_EQUAL( (std::string) copy_of_p6, "test char") + TEST_EQUAL( (std::string) copy_of_p7, "test string") + TEST_EQUAL( copy_of_p8 == ListUtils::create("test string,string2,last string"), true) + TEST_EQUAL( (copy_of_p9.isEmpty()), true) + TEST_EQUAL( copy_of_p10 == ListUtils::create("1,2,3,4,5"), true) + TEST_EQUAL( copy_of_p11 == ListUtils::create("1.2,2.3,3.4"), true) + + TEST_EQUAL(p1 == empty, true) + TEST_EQUAL(p3 == empty, true) + TEST_EQUAL(p4 == empty, true) + TEST_EQUAL(p5 == empty, true) + TEST_EQUAL(p6 == empty, true) + TEST_EQUAL(p7 == empty, true) + TEST_EQUAL(p8 == empty, true) + TEST_EQUAL(p9 == empty, true) + TEST_EQUAL(p10 == empty, true) + TEST_EQUAL(p11 == empty, true) + } + END_SECTION + +// assignment operator + START_SECTION((ParamValue& operator=(const ParamValue&))) + { + ParamValue p1((double) 1.23); + ParamValue p3((float) 1.23); + ParamValue p4((Int) -3); + ParamValue p5((UInt) 123); + ParamValue p6("test char"); + ParamValue p7(std::string("test string")); + ParamValue p8({"test string","string2","last string"}); + ParamValue p9; + ParamValue p10(vector{1,2,3,4,5}); + ParamValue p11(vector{1.2,2.3,3.4}); + ParamValue copy_of_p; + copy_of_p = p1; + TEST_REAL_SIMILAR( (double) copy_of_p, 1.23) + copy_of_p = p3; + TEST_REAL_SIMILAR( (float) copy_of_p, 1.23) + copy_of_p = p4; + TEST_EQUAL( (Int) copy_of_p, -3) + copy_of_p = p5; + TEST_EQUAL( (UInt) copy_of_p, 123) + copy_of_p = p6; + TEST_EQUAL( (std::string) copy_of_p, "test char") + copy_of_p = p7; + TEST_EQUAL( (std::string) copy_of_p, "test string") + copy_of_p = p8; + TEST_EQUAL( copy_of_p == ListUtils::create("test string,string2,last string"), true) + copy_of_p = p9; + TEST_EQUAL( (copy_of_p.isEmpty()), true) + copy_of_p = p10; + TEST_EQUAL(copy_of_p == ListUtils::create("1,2,3,4,5"), true) + copy_of_p = p11; + TEST_EQUAL(copy_of_p == ListUtils::create("1.2,2.3,3.4"), true) + } + END_SECTION + +// move assignment operator + START_SECTION(( ParamValue& operator=(ParamValue&&) noexcept )) + { + // Ensure that ParamValue has a no-except move assignment operator. + TEST_EQUAL(noexcept(declval() = declval()), true) + + ParamValue empty; + ParamValue p1((double) 1.23); + ParamValue p3((float) 1.23); + ParamValue p4((Int) -3); + ParamValue p5((UInt) 123); + ParamValue p6("test char"); + ParamValue p7(std::string("test string")); + ParamValue p8({"test string","string2","last string"}); + ParamValue p9; + ParamValue p10(vector{1,2,3,4,5}); + ParamValue p11(vector{1.2,2.3,3.4}); + ParamValue copy_of_p; + copy_of_p = std::move(p1); + TEST_REAL_SIMILAR( (double) copy_of_p, 1.23) + copy_of_p = std::move(p3); + TEST_REAL_SIMILAR( (float) copy_of_p, 1.23) + copy_of_p = std::move(p4); + TEST_EQUAL( (Int) copy_of_p, -3) + copy_of_p = std::move(p5); + TEST_EQUAL( (UInt) copy_of_p, 123) + copy_of_p = std::move(p6); + TEST_EQUAL( (std::string) copy_of_p, "test char") + copy_of_p = std::move(p7); + TEST_EQUAL( (std::string) copy_of_p, "test string") + copy_of_p = std::move(p8); + TEST_EQUAL( copy_of_p == ListUtils::create("test string,string2,last string"), true) + copy_of_p = std::move(p9); + TEST_EQUAL( (copy_of_p.isEmpty()), true) + copy_of_p = std::move(p10); + TEST_EQUAL(copy_of_p == ListUtils::create("1,2,3,4,5"), true) + copy_of_p = std::move(p11); + TEST_EQUAL(copy_of_p == ListUtils::create("1.2,2.3,3.4"), true) + + TEST_EQUAL(p1 == empty, true) + TEST_EQUAL(p3 == empty, true) + TEST_EQUAL(p4 == empty, true) + TEST_EQUAL(p5 == empty, true) + TEST_EQUAL(p6 == empty, true) + TEST_EQUAL(p7 == empty, true) + TEST_EQUAL(p8 == empty, true) + TEST_EQUAL(p9 == empty, true) + TEST_EQUAL(p10 == empty, true) + TEST_EQUAL(p11 == empty, true) + } + END_SECTION + +// Is ParamValue object empty? + START_SECTION((bool isEmpty() const)) + { + ParamValue p1; + TEST_EQUAL(p1.isEmpty(), true); + + ParamValue p2((float)1.2); + TEST_EQUAL(p2.isEmpty(), false); + TEST_REAL_SIMILAR((float) p2, 1.2); + + ParamValue p3(""); + TEST_EQUAL(p3.isEmpty(), false); // empty string does not count as empty! + + ParamValue p4("2"); + TEST_EQUAL(p4.isEmpty(), false) + TEST_EQUAL((std::string) p4, "2"); + } + END_SECTION + +// conversion operators + START_SECTION((operator std::string() const)) + ParamValue d((std::string) "test string"); + std::string k = d; + TEST_EQUAL(k,"test string") + END_SECTION + + START_SECTION((operator vector() const)) + vector sl = {"test string list"}; + ParamValue d(sl); + vector sl_op = d; + TEST_EQUAL(sl_op == d, true) + END_SECTION + + START_SECTION((vector toStringVector() const)) + vector sl = {"test string list"}; + ParamValue d(sl); + vector sl_op = d.toStringVector(); + TEST_EQUAL(sl_op == d, true) + END_SECTION + + START_SECTION((operator vector() const)) + vector il = {1, 2}; + ParamValue d(il); + vector il_op = d; + TEST_EQUAL(il_op == il, true) + TEST_EXCEPTION(Exception::ConversionError, vector sl = ParamValue("abc,ab");) + END_SECTION + + START_SECTION((vector toIntVector() const)) + vector il = {1, 2}; + ParamValue d(il); + vector il_op = d.toIntVector(); + TEST_EQUAL(il_op == il, true) + TEST_EXCEPTION(Exception::ConversionError, vector sl = ParamValue("abc,ab").toStringVector();) + END_SECTION + + START_SECTION((operator vector() const)) + vector dl = {1.2, 22.34455}; + ParamValue d(dl); + vector dl_op = d; + TEST_EQUAL(dl_op == d, true); + END_SECTION + + START_SECTION((DoubleList toDoubleVector() const)) + vector dl = {1.2, 22.34455}; + ParamValue d(dl); + vector dl_op = d.toDoubleVector(); + TEST_EQUAL(dl_op == d, true); + END_SECTION + + START_SECTION((operator long double() const)) + ParamValue d(5.4L); + long double k = d; + TEST_REAL_SIMILAR(k,5.4L) + END_SECTION + + START_SECTION((operator double() const)) + ParamValue d(5.4); + double k = d; + TEST_REAL_SIMILAR(k,5.4) + END_SECTION + + START_SECTION((operator float() const)) + ParamValue d(5.4f); + float k = d; + TEST_REAL_SIMILAR(k,5.4f) + END_SECTION + + START_SECTION((operator int() const )) + ParamValue d((Int) -55); + int k = d; + TEST_EQUAL(k,-55) + + TEST_EXCEPTION(Exception::ConversionError, (int)ParamValue(55.4)) + END_SECTION + + START_SECTION((operator unsigned int() const )) + ParamValue d((Int) 55); + unsigned int k = d; + TEST_EQUAL(k,55) + + TEST_EXCEPTION(Exception::ConversionError, (unsigned int)ParamValue(-55)) + TEST_EXCEPTION(Exception::ConversionError, (unsigned int)ParamValue(55.4)) + END_SECTION + + START_SECTION((operator short int() const)) + ParamValue d((short int) -55); + short int k = d; + TEST_EQUAL(k,-55) + + TEST_EXCEPTION(Exception::ConversionError, (short int)ParamValue(55.4)) + END_SECTION + + START_SECTION((operator unsigned short int() const)) + ParamValue d((short int) 55); + unsigned short int k = d; + TEST_EQUAL(k,55) + + TEST_EXCEPTION(Exception::ConversionError, (unsigned short int)ParamValue(-55)) + TEST_EXCEPTION(Exception::ConversionError, (unsigned short int)ParamValue(55.4)) + END_SECTION + + START_SECTION((operator long int() const)) + ParamValue d((long int) -55); + long int k = d; + TEST_EQUAL(k,-55) + + TEST_EXCEPTION(Exception::ConversionError, (long int)ParamValue(55.4)) + END_SECTION + + START_SECTION((operator unsigned long int() const)) + ParamValue d((long int) 55); + unsigned long int k = d; + TEST_EQUAL(k,55) + + TEST_EXCEPTION(Exception::ConversionError, (unsigned long int)ParamValue(-55)) + TEST_EXCEPTION(Exception::ConversionError, (unsigned long int)ParamValue(55.4)) + END_SECTION + + START_SECTION((operator long long() const)) + { + { + ParamValue d((long long) 55); + long long k = d; + TEST_EQUAL(k,55) + } + { + ParamValue d((long long) -1); + long long k = d; + TEST_EQUAL(k,-1) + } + { + ParamValue d((SignedSize) -55); + SignedSize k = d; + TEST_EQUAL(k,-55) + } + + TEST_EXCEPTION(Exception::ConversionError, (long int)ParamValue(55.4)) + } + END_SECTION + + START_SECTION((operator unsigned long long() const)) + { + { + ParamValue d((unsigned long long) 55); + unsigned long long k = d; + TEST_EQUAL(k,55) + } + { + ParamValue d((Size) 55); + Size k = d; + TEST_EQUAL(k,55) + } + + TEST_EXCEPTION(Exception::ConversionError, (unsigned long int)ParamValue(-55)) + TEST_EXCEPTION(Exception::ConversionError, (unsigned long int)ParamValue(55.4)) + } + END_SECTION + + START_SECTION(([EXTRA] friend bool operator==(const ParamValue&, const ParamValue&))) + { + ParamValue a(5.0); + ParamValue b(5.0); + TEST_EQUAL(a==b,true); + a = ParamValue((double)15.13); + b = ParamValue((double)15.13); + TEST_EQUAL(a==b,true); + a = ParamValue((float)15.13); + b = ParamValue((float)(17-1.87)); + TEST_EQUAL(a==b,true); + a = ParamValue((Int)5); + b = ParamValue((Int)5); + TEST_EQUAL(a==b,true); + a = ParamValue((UInt)5000); + b = ParamValue((UInt)5000); + TEST_EQUAL(a==b,true); + a = ParamValue("hello"); + b = ParamValue(std::string("hello")); + TEST_EQUAL(a==b,true); + a = ParamValue((float)15.13); + b = ParamValue((float)(15.13001)); + TEST_EQUAL(a==b,false); + } + END_SECTION + + START_SECTION(([EXTRA] friend bool operator!=(const ParamValue&, const ParamValue&))) + { + ParamValue a(5.0); + ParamValue b(5.1); + TEST_EQUAL(a!=b,true); + a = ParamValue((double)15.13001); + b = ParamValue((double)15.13); + TEST_EQUAL(a!=b,true); + + a = ParamValue("hello"); + b = ParamValue(std::string("hello")); + TEST_EQUAL(a!=b,false); + } + END_SECTION + + START_SECTION((const char* toChar() const)) + ParamValue a; + TEST_EQUAL(a.toChar() == nullptr, true) + a = ParamValue("hello"); + TEST_STRING_EQUAL(a.toChar(),"hello") + a = ParamValue(5); + TEST_EXCEPTION(Exception::ConversionError, a.toChar() ) + END_SECTION + + START_SECTION((String toString(bool full_precision) const)) + ParamValue a; + TEST_EQUAL(a.toString(), "") + a = ParamValue("hello"); + TEST_EQUAL(a.toString(),"hello") + a = ParamValue(5); + TEST_EQUAL(a.toString(), "5") + a = ParamValue(47.11); + TEST_EQUAL(a.toString(), "47.109999999999999") + TEST_EQUAL(a.toString(false), "47.11") + a = ParamValue(-23456.78); + TEST_EQUAL(a.toString(), "-2.345678e04") + a = ParamValue(ListUtils::create("test string,string2,last string")); + TEST_EQUAL(a.toString(), "[test string, string2, last string]") + a = ParamValue(ListUtils::create("1,2,3,4,5")); + TEST_EQUAL(a.toString(),"[1, 2, 3, 4, 5]") + a = ParamValue(ListUtils::create("1.2,47.11,1.2345678e05")); + TEST_EQUAL(a.toString(),"[1.2, 47.109999999999999, 1.2345678e05]") + TEST_EQUAL(a.toString(false), "[1.2, 47.11, 1.235e05]") + END_SECTION + + START_SECTION((bool toBool() const)) + //valid cases + ParamValue a("true"); + TEST_EQUAL(a.toBool(),true) + a = ParamValue("false"); + TEST_EQUAL(a.toBool(),false) + + //invalid cases + a = ParamValue(); + TEST_EXCEPTION(Exception::ConversionError, a.toBool() ) + a = ParamValue("bla"); + TEST_EXCEPTION(Exception::ConversionError, a.toBool() ) + a = ParamValue(12); + TEST_EXCEPTION(Exception::ConversionError, a.toBool() ) + a = ParamValue(34.45); + TEST_EXCEPTION(Exception::ConversionError, a.toBool() ) + END_SECTION + + START_SECTION(([EXTRA] friend std::ostream& operator<<(std::ostream&, const ParamValue&))) + ParamValue a((Int)5), b((UInt)100), c((double)1.111), d((double)1.1), e("hello "), f(std::string("world")), g; + std::ostringstream os; + os << a << b << c << d << e << f << g; + TEST_EQUAL(os.str(),"51001.1111.1hello world") + END_SECTION + + START_SECTION((DataType valueType() const)) + ParamValue a; + TEST_EQUAL(a.valueType(), ParamValue::EMPTY_VALUE); + + ParamValue a1(1.45); + TEST_EQUAL(a1.valueType(), ParamValue::DOUBLE_VALUE); + + ParamValue a2(1.34f); + TEST_EQUAL(a2.valueType(), ParamValue::DOUBLE_VALUE); + + ParamValue a3(123); + TEST_EQUAL(a3.valueType(), ParamValue::INT_VALUE); + + ParamValue a4("bla"); + TEST_EQUAL(a4.valueType(), ParamValue::STRING_VALUE); + + ParamValue a5(ListUtils::create("test string,string2,last string")); + TEST_EQUAL(a5.valueType(), ParamValue::STRING_LIST) + + ParamValue a6(UInt(2)); + TEST_EQUAL(a6.valueType(), ParamValue::INT_VALUE); + + ParamValue a7(ListUtils::create("1,2,3")); + TEST_EQUAL(a7.valueType(),ParamValue::INT_LIST) + + ParamValue a8(ListUtils::create("1.2,32.4567")); + TEST_EQUAL(a8.valueType(),ParamValue::DOUBLE_LIST); + END_SECTION + + START_SECTION((ParamValue& operator=(const char*))) + { + const char * v = "value"; + ParamValue a("v"); + a = v; + TEST_EQUAL(a, "value") + } + END_SECTION + + START_SECTION((ParamValue& operator=(const std::string&))) + { + std::string v = "value"; + ParamValue a("v"); + a = v; + TEST_EQUAL(a, "value") + } + END_SECTION + + START_SECTION((ParamValue& operator=(const vector&))) + { + vector v = {"value","value2"}; + ParamValue a("v"); + a = v; + vector sla = a; + TEST_EQUAL(sla.size(), 2) + ABORT_IF(sla.size() != 2) + TEST_EQUAL(sla[0], "value") + TEST_EQUAL(sla[1], "value2") + } + END_SECTION + + START_SECTION((ParamValue& operator=(const vector&))) + { + vector v = {2,-3}; + ParamValue a("v"); + a = v; + vector dv = a; + TEST_EQUAL(dv.size(), 2) + ABORT_IF(dv.size() != 2) + TEST_EQUAL(dv[0], 2) + TEST_EQUAL(dv[1], -3) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const vector&))) + { + vector v = {2.14,-3.45}; + ParamValue a("v"); + a = v; + vector adl = a; + TEST_EQUAL(adl.size(), 2) + ABORT_IF(adl.size() != 2) + TEST_EQUAL(adl[0], 2.14) + TEST_EQUAL(adl[1], -3.45) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const long double))) + { + const long double v = 2.44; + ParamValue a("v"); + a = v; + TEST_EQUAL((long double)a, 2.44) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const double))) + { + const double v = 2.44; + ParamValue a("v"); + a = v; + TEST_EQUAL((double)a, 2.44) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const float))) + { + const float v = 2.44f; + ParamValue a("v"); + a = v; + TEST_EQUAL((float)a, 2.44f) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const short int))) + { + const short int v = 2; + ParamValue a("v"); + a = v; + TEST_EQUAL((short int)a, 2) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const unsigned short int))) + { + const unsigned short int v = 2; + ParamValue a("v"); + a = v; + TEST_EQUAL((unsigned short int)a, 2) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const int))) + { + const int v = 2; + ParamValue a("v"); + a = v; + TEST_EQUAL((int)a, 2) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const unsigned))) + { + const unsigned v = 2; + ParamValue a("v"); + a = v; + TEST_EQUAL((unsigned)a, 2) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const long int))) + { + const long int v = 2; + ParamValue a("v"); + a = v; + TEST_EQUAL((long int)a, 2) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const unsigned long))) + { + const unsigned long v = 2; + ParamValue a("v"); + a = v; + TEST_EQUAL((unsigned long)a, 2) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const long long))) + { + const long long v = 2; + ParamValue a("v"); + a = v; + TEST_EQUAL((long long)a, 2) + } + END_SECTION + + START_SECTION((ParamValue& operator=(const unsigned long long))) + { + const unsigned long long v = 2; + ParamValue a("v"); + a = v; + TEST_EQUAL((unsigned long long)a, 2) + } + END_SECTION + +///////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////// +END_TEST + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif diff --git a/src/tests/class_tests/openms/source/ParamXMLFile_test.cpp b/src/tests/class_tests/openms/source/ParamXMLFile_test.cpp index f9fc39e8c71..644f2f955c9 100644 --- a/src/tests/class_tests/openms/source/ParamXMLFile_test.cpp +++ b/src/tests/class_tests/openms/source/ParamXMLFile_test.cpp @@ -76,7 +76,7 @@ p.setValue("test2:float",17.5f); p.setValue("test2:string","test2"); p.setValue("test2:int",18); p.setSectionDescription("test","sectiondesc"); -p.addTags("test:float", ListUtils::create("a,b,c")); +p.addTags("test:float", {"a","b","c"}); START_SECTION((void store(const String& filename, const Param& param) const)) ParamXMLFile paramFile; @@ -86,7 +86,7 @@ START_SECTION((void store(const String& filename, const Param& param) const)) p2.setValue("test:b:b1", 47.1); p2.setSectionDescription("test:b","bdesc\"<>\nnewline"); p2.setValue("test2:a:a1", 47.1); - p2.setValue("test2:b:b1", 47.1,"",ListUtils::create("advanced")); + p2.setValue("test2:b:b1", 47.1,"",{"advanced"}); p2.setSectionDescription("test2:a","adesc"); //exception @@ -119,7 +119,7 @@ START_SECTION((void store(const String& filename, const Param& param) const)) //advanced NEW_TMP_FILE(filename); Param p7; - p7.setValue("true",5,"",ListUtils::create("advanced")); + p7.setValue("true",5,"",{"advanced"}); p7.setValue("false",5,""); paramFile.store(filename,p7); @@ -151,7 +151,7 @@ START_SECTION((void store(const String& filename, const Param& param) const)) p5.setMinFloat("float_min_max",0.1); p5.setMaxFloat("float_min_max",10.1); - vector strings; + vector strings; p5.setValue("string","bli"); strings.push_back("bla"); strings.push_back("bluff"); @@ -159,11 +159,9 @@ START_SECTION((void store(const String& filename, const Param& param) const)) p5.setValidStrings("string_2",strings); //list restrictions - vector strings2; - strings2.push_back("xml"); - strings2.push_back("txt"); - p5.setValue("stringlist2",ListUtils::create("a.txt,b.xml,c.pdf")); - p5.setValue("stringlist",ListUtils::create("aa.C,bb.h,c.doxygen")); + vector strings2 = {"xml", "txt"}; + p5.setValue("stringlist2",std::vector{"a.txt","b.xml","c.pdf"}); + p5.setValue("stringlist",std::vector{"aa.C","bb.h","c.doxygen"}); p5.setValidStrings("stringlist2",strings2); p5.setValue("intlist",ListUtils::create("2,5,10")); @@ -249,21 +247,21 @@ END_SECTION START_SECTION((void writeXMLToStream(std::ostream *os_ptr, const Param ¶m) const )) { Param p; - p.setValue("stringlist", ListUtils::create("a,bb,ccc"), "StringList Description"); + p.setValue("stringlist", std::vector{"a","bb","ccc"}, "StringList Description"); p.setValue("intlist", ListUtils::create("1,22,333")); p.setValue("item", String("bla")); - p.setValue("stringlist2", ListUtils::create("")); + p.setValue("stringlist2", std::vector()); p.setValue("intlist2", ListUtils::create("")); p.setValue("item1", 7); p.setValue("intlist3", ListUtils::create("1")); - p.setValue("stringlist3", ListUtils::create("1")); + p.setValue("stringlist3", std::vector{"1"}); p.setValue("item3", 7.6); p.setValue("doublelist", ListUtils::create("1.22,2.33,4.55")); p.setValue("doublelist3", ListUtils::create("1.4")); p.setValue("file_parameter", "", "This is a file parameter."); p.addTag("file_parameter", "input file"); - p.setValidStrings("file_parameter", ListUtils::create("*.mzML,*.mzXML")); - p.setValue("advanced_parameter", "", "This is an advanced parameter.", ListUtils::create("advanced")); + p.setValidStrings("file_parameter", std::vector{"*.mzML","*.mzXML"}); + p.setValue("advanced_parameter", "", "This is an advanced parameter.", {"advanced"}); p.setValue("flag", "false", "This is a flag i.e. in a command line input it does not need a value."); p.setValidStrings("flag",{"true","false"}); p.setValue("noflagJustTrueFalse", "true", "This is not a flag but has a boolean meaning."); @@ -282,14 +280,14 @@ START_SECTION([EXTRA] loading and storing of lists) ParamXMLFile paramFile; Param p; - p.setValue("stringlist", ListUtils::create("a,bb,ccc")); + p.setValue("stringlist", std::vector{"a","bb","ccc"}); p.setValue("intlist", ListUtils::create("1,22,333")); p.setValue("item", String("bla")); - p.setValue("stringlist2", ListUtils::create("")); + p.setValue("stringlist2", std::vector()); p.setValue("intlist2", ListUtils::create("")); p.setValue("item1", 7); p.setValue("intlist3", ListUtils::create("1")); - p.setValue("stringlist3", ListUtils::create("1")); + p.setValue("stringlist3", std::vector{"1"}); p.setValue("item3", 7.6); p.setValue("doublelist", ListUtils::create("1.22,2.33,4.55")); p.setValue("doublelist2", ListUtils::create("")); @@ -304,50 +302,50 @@ START_SECTION([EXTRA] loading and storing of lists) TEST_EQUAL(p2.size(),12); - TEST_EQUAL(p2.getValue("stringlist").valueType(), DataValue::STRING_LIST) - StringList list = p2.getValue("stringlist"); + TEST_EQUAL(p2.getValue("stringlist").valueType(), ParamValue::STRING_LIST) + std::vector list = p2.getValue("stringlist"); TEST_EQUAL(list.size(),3) TEST_EQUAL(list[0],"a") TEST_EQUAL(list[1],"bb") TEST_EQUAL(list[2],"ccc") - TEST_EQUAL(p2.getValue("stringlist2").valueType(), DataValue::STRING_LIST) + TEST_EQUAL(p2.getValue("stringlist2").valueType(), ParamValue::STRING_LIST) list = p2.getValue("stringlist2"); TEST_EQUAL(list.size(),0) - TEST_EQUAL(p2.getValue("stringlist").valueType(), DataValue::STRING_LIST) + TEST_EQUAL(p2.getValue("stringlist").valueType(), ParamValue::STRING_LIST) list = p2.getValue("stringlist3"); TEST_EQUAL(list.size(),1) TEST_EQUAL(list[0],"1") - TEST_EQUAL(p2.getValue("intlist").valueType(), DataValue::INT_LIST) + TEST_EQUAL(p2.getValue("intlist").valueType(), ParamValue::INT_LIST) IntList intlist = p2.getValue("intlist"); TEST_EQUAL(intlist.size(),3); TEST_EQUAL(intlist[0], 1) TEST_EQUAL(intlist[1], 22) TEST_EQUAL(intlist[2], 333) - TEST_EQUAL(p2.getValue("intlist2").valueType(),DataValue::INT_LIST) + TEST_EQUAL(p2.getValue("intlist2").valueType(),ParamValue::INT_LIST) intlist = p2.getValue("intlist2"); TEST_EQUAL(intlist.size(),0) - TEST_EQUAL(p2.getValue("intlist3").valueType(),DataValue::INT_LIST) + TEST_EQUAL(p2.getValue("intlist3").valueType(),ParamValue::INT_LIST) intlist = p2.getValue("intlist3"); TEST_EQUAL(intlist.size(),1) TEST_EQUAL(intlist[0],1) - TEST_EQUAL(p2.getValue("doublelist").valueType(), DataValue::DOUBLE_LIST) + TEST_EQUAL(p2.getValue("doublelist").valueType(), ParamValue::DOUBLE_LIST) DoubleList doublelist = p2.getValue("doublelist"); TEST_EQUAL(doublelist.size(),3); TEST_EQUAL(doublelist[0], 1.22) TEST_EQUAL(doublelist[1], 2.33) TEST_EQUAL(doublelist[2], 4.55) - TEST_EQUAL(p2.getValue("doublelist2").valueType(),DataValue::DOUBLE_LIST) + TEST_EQUAL(p2.getValue("doublelist2").valueType(),ParamValue::DOUBLE_LIST) doublelist = p2.getValue("doublelist2"); TEST_EQUAL(doublelist.size(),0) - TEST_EQUAL(p2.getValue("doublelist3").valueType(),DataValue::DOUBLE_LIST) + TEST_EQUAL(p2.getValue("doublelist3").valueType(),ParamValue::DOUBLE_LIST) doublelist = p2.getValue("doublelist3"); TEST_EQUAL(doublelist.size(),1) TEST_EQUAL(doublelist[0],1.4) diff --git a/src/tests/class_tests/openms/source/Param_test.cpp b/src/tests/class_tests/openms/source/Param_test.cpp index d3ac1200e40..370c0612e05 100644 --- a/src/tests/class_tests/openms/source/Param_test.cpp +++ b/src/tests/class_tests/openms/source/Param_test.cpp @@ -39,8 +39,6 @@ #include #include -#include -#include #include #include // for "ParameterInformation" @@ -70,8 +68,8 @@ START_SECTION(([Param::ParamEntry] ~ParamEntry())) delete pe_ptr; END_SECTION -START_SECTION(([Param::ParamEntry] ParamEntry(const String &n, const DataValue &v, const String &d, const StringList &t=StringList()))) - Param::ParamEntry pe("n","v","d",ListUtils::create("advanced")); +START_SECTION(([Param::ParamEntry] ParamEntry(const std::string &n, const DataValue &v, const std::string &d, const std::vector &t=std::vector()))) + Param::ParamEntry pe("n","v","d",{"advanced"}); TEST_EQUAL(pe.name,"n") TEST_EQUAL(pe.description,"d") TEST_EQUAL(pe.value,"v") @@ -84,10 +82,10 @@ START_SECTION(([Param::ParamEntry] ParamEntry(const String &n, const DataValue & TEST_EQUAL(pe.tags.count("advanced")==1,false) END_SECTION -START_SECTION(([Param::ParamEntry] bool isValid(String& message) const)) +START_SECTION(([Param::ParamEntry] bool isValid(std::string& message) const)) Param p; - String m; + std::string m; p.setValue("int",5); TEST_EQUAL(p.getEntry("int").isValid(m),true); p.setMinInt("int",5); @@ -116,7 +114,7 @@ START_SECTION(([Param::ParamEntry] bool isValid(String& message) const)) TEST_EQUAL(p.getEntry("float").isValid(m),false); - vector strings; + vector strings; strings.push_back("bla"); strings.push_back("bluff"); p.setValue("string","bli"); @@ -132,8 +130,8 @@ START_SECTION(([Param::ParamEntry] bool isValid(String& message) const)) END_SECTION START_SECTION(([Param::ParamEntry] bool operator==(const ParamEntry& rhs) const)) - Param::ParamEntry n1("n","d","v",ListUtils::create("advanced")); - Param::ParamEntry n2("n","d","v",ListUtils::create("advanced")); + Param::ParamEntry n1("n","d","v",{"advanced"}); + Param::ParamEntry n2("n","d","v",{"advanced"}); TEST_EQUAL(n1==n2,true) @@ -166,7 +164,7 @@ START_SECTION(([Param::ParamNode] ~ParamNode())) delete pn_ptr; END_SECTION -START_SECTION(([Param::ParamNode] ParamNode(const String& n, const String& d))) +START_SECTION(([Param::ParamNode] ParamNode(const std::string& n, const std::string& d))) Param::ParamNode n("n","d"); TEST_EQUAL(n.name,"n") TEST_EQUAL(n.description,"d") @@ -211,7 +209,7 @@ START_SECTION(([Param::ParamNode] bool operator==(const ParamNode& rhs) const)) TEST_EQUAL(n1==n2,true) END_SECTION -START_SECTION(([Param::ParamNode] String suffix(const String &key) const )) +START_SECTION(([Param::ParamNode] std::string suffix(const std::string &key) const )) Param::ParamNode node; TEST_EQUAL(node.suffix(""),"") TEST_EQUAL(node.suffix("A"),"A") @@ -246,7 +244,7 @@ START_SECTION(([Param::ParamNode] Size size() const )) TEST_EQUAL(pn.nodes[1].size(),1) END_SECTION -START_SECTION(([Param::ParamNode] EntryIterator findEntry(const String& name))) +START_SECTION(([Param::ParamNode] EntryIterator findEntry(const std::string& name))) TEST_EQUAL(pn.findEntry("A")==pn.entries.end(),true) TEST_EQUAL(pn.findEntry("B")!=pn.entries.end(),true) TEST_EQUAL(pn.findEntry("C")==pn.entries.end(),true) @@ -257,7 +255,7 @@ START_SECTION(([Param::ParamNode] EntryIterator findEntry(const String& name))) TEST_EQUAL(pn.findEntry("H")==pn.entries.end(),true) END_SECTION -START_SECTION(([Param::ParamNode] NodeIterator findNode(const String& name))) +START_SECTION(([Param::ParamNode] NodeIterator findNode(const std::string& name))) TEST_EQUAL(pn.findNode("A")==pn.nodes.end(),true) TEST_EQUAL(pn.findNode("B")!=pn.nodes.end(),true) TEST_EQUAL(pn.findNode("C")!=pn.nodes.end(),true) @@ -268,7 +266,7 @@ START_SECTION(([Param::ParamNode] NodeIterator findNode(const String& name))) TEST_EQUAL(pn.findNode("H")==pn.nodes.end(),true) END_SECTION -START_SECTION(([Param::ParamNode] ParamNode* findParentOf(const String &name))) +START_SECTION(([Param::ParamNode] ParamNode* findParentOf(const std::string &name))) TEST_EQUAL(pn.findParentOf("A"),pn_nullPointer) TEST_EQUAL(pn.findParentOf("B"),&pn) TEST_EQUAL(pn.findParentOf("C"),&pn) @@ -282,7 +280,7 @@ START_SECTION(([Param::ParamNode] ParamNode* findParentOf(const String &name))) TEST_EQUAL(pn.findParentOf("H:C:"),pn_nullPointer) END_SECTION -START_SECTION(([Param::ParamNode] ParamEntry* findEntryRecursive(const String& name))) +START_SECTION(([Param::ParamNode] ParamEntry* findEntryRecursive(const std::string& name))) TEST_EQUAL(pn.findEntryRecursive("A"),pe_nullPointer) TEST_EQUAL(pn.findEntryRecursive("B"),&(pn.entries[0])) TEST_EQUAL(pn.findEntryRecursive("C"),pe_nullPointer) @@ -307,9 +305,9 @@ END_SECTION // |-F // |-H(5) -START_SECTION(([Param::ParamNode] void insert(const ParamNode& node, const String& prefix = ""))) +START_SECTION(([Param::ParamNode] void insert(const ParamNode& node, const std::string& prefix = ""))) Param::ParamNode node("",""); - node.entries.push_back(Param::ParamEntry("H",5,"",ListUtils::create("advanced"))); + node.entries.push_back(Param::ParamEntry("H",5,"",{"advanced"})); pn.insert(node,"F"); TEST_NOT_EQUAL(pn.findEntryRecursive("F:H"),pe_nullPointer) @@ -330,8 +328,8 @@ START_SECTION(([Param::ParamNode] void insert(const ParamNode& node, const Strin TEST_NOT_EQUAL(pn.findEntryRecursive("QW:H"),pe_nullPointer) END_SECTION -START_SECTION(([Param::ParamNode] void insert(const ParamEntry& entry, const String& prefix = ""))) - Param::ParamEntry entry("H","",5,ListUtils::create("advanced")); +START_SECTION(([Param::ParamNode] void insert(const ParamEntry& entry, const std::string& prefix = ""))) + Param::ParamEntry entry("H","","5",{"advanced"}); pn.insert(entry); TEST_NOT_EQUAL(pn.findEntryRecursive("H"),pe_nullPointer) @@ -370,7 +368,7 @@ END_SECTION START_SECTION(([Param::ParamIterator] const Param::ParamEntry& operator*())) Param::ParamNode node; - node.entries.push_back(Param::ParamEntry("name","value","description",ListUtils::create("advanced"))); + node.entries.push_back(Param::ParamEntry("name","value","description",{"advanced"})); Param::ParamIterator it(node); TEST_EQUAL((*it).name,"name") TEST_EQUAL((*it).value,"value"); @@ -380,7 +378,7 @@ END_SECTION START_SECTION(([Param::ParamIterator] const Param::ParamEntry* operator->())) Param::ParamNode node; - node.entries.push_back(Param::ParamEntry("name","value","description",ListUtils::create("advanced"))); + node.entries.push_back(Param::ParamEntry("name","value","description",{"advanced"})); Param::ParamIterator it(node); TEST_EQUAL(it->name,"name"); TEST_EQUAL(it->value,"value"); @@ -414,9 +412,9 @@ root.nodes.push_back(t); START_SECTION(([Param::ParamIterator] ParamIterator& operator++())) Param::ParamNode node; - node.entries.push_back(Param::ParamEntry("name","value","description",ListUtils::create("advanced"))); + node.entries.push_back(Param::ParamEntry("name","value","description",{"advanced"})); node.entries.push_back(Param::ParamEntry("name2","value2","description2")); - node.entries.push_back(Param::ParamEntry("name3","value3","description3",ListUtils::create("advanced"))); + node.entries.push_back(Param::ParamEntry("name3","value3","description3",{"advanced"})); //linear list Param::ParamIterator it(node); @@ -502,9 +500,9 @@ END_SECTION START_SECTION(([Param::ParamIterator] ParamIterator operator++(int))) Param::ParamNode node; - node.entries.push_back(Param::ParamEntry("name","value","description",ListUtils::create("advanced"))); + node.entries.push_back(Param::ParamEntry("name","value","description",{"advanced"})); node.entries.push_back(Param::ParamEntry("name2","value2","description2")); - node.entries.push_back(Param::ParamEntry("name3","value3","description3",ListUtils::create("advanced"))); + node.entries.push_back(Param::ParamEntry("name3","value3","description3",{"advanced"})); //linear list Param::ParamIterator it(node), it2(node); @@ -520,7 +518,7 @@ START_SECTION(([Param::ParamIterator] ParamIterator operator++(int))) TEST_EQUAL(it2->tags.count("advanced")==1,true); END_SECTION -START_SECTION(([Param::ParamIterator] String getName() const)) +START_SECTION(([Param::ParamIterator] std::string getName() const)) Param::ParamIterator it(root); TEST_EQUAL(it.getName(),"A"); @@ -648,42 +646,56 @@ START_SECTION((~Param())) delete d10_ptr; END_SECTION -START_SECTION((bool exists(const String& key) const)) +START_SECTION((bool exists(const std::string& key) const)) Param p; TEST_EQUAL(p.exists(""), false) TEST_EQUAL(p.exists("key"), false) TEST_EQUAL(p.exists("key:value"), false) END_SECTION -START_SECTION((const DataValue& getValue(const String &key) const)) +START_SECTION((bool hasSection(const std::string& key) const)) + Param p; + p.addSection("test", ""); + p.addSection("test:test", ""); + TEST_EQUAL(p.hasSection("test"), true) + TEST_EQUAL(p.hasSection("test:test"), true) + TEST_EQUAL(p.hasSection("test:"), true) + TEST_EQUAL(p.hasSection("test:test:"), true) + TEST_EQUAL(p.hasSection("sectionThatDoesNotExist"), false) + TEST_EQUAL(p.hasSection("AnotherSection:"), false) + TEST_EQUAL(p.hasSection("Section:WithinSection"), false) + TEST_EQUAL(p.hasSection("Section:WithinSection:"), false) +END_SECTION + +START_SECTION((const DataValue& getValue(const std::string &key) const)) Param p; TEST_EXCEPTION(Exception::ElementNotFound, p.getValue("")) TEST_EXCEPTION(Exception::ElementNotFound, p.getValue("key")) TEST_EXCEPTION(Exception::ElementNotFound, p.getValue("key:value")) END_SECTION -START_SECTION((const String& getSectionDescription(const String& key) const)) +START_SECTION((const std::string& getSectionDescription(const std::string& key) const)) Param p; TEST_EQUAL(p.getSectionDescription(""),"") TEST_EQUAL(p.getSectionDescription("key"),"") TEST_EQUAL(p.getSectionDescription("key:value"),"") END_SECTION -START_SECTION((const String& getDescription(const String &key) const)) +START_SECTION((const std::string& getDescription(const std::string &key) const)) Param p; TEST_EXCEPTION(Exception::ElementNotFound, p.getDescription("")) TEST_EXCEPTION(Exception::ElementNotFound, p.getDescription("key")) TEST_EXCEPTION(Exception::ElementNotFound, p.getDescription("key:value")) END_SECTION -START_SECTION((const ParamEntry& getEntry(const String &key) const)) +START_SECTION((const ParamEntry& getEntry(const std::string &key) const)) Param p; TEST_EXCEPTION(Exception::ElementNotFound, p.getEntry("")) TEST_EXCEPTION(Exception::ElementNotFound, p.getEntry("key")) TEST_EXCEPTION(Exception::ElementNotFound, p.getEntry("key:value")) END_SECTION -START_SECTION((void setValue(const String &key, const DataValue& value, const String &description="", const StringList &tags=StringList()))) +START_SECTION((void setValue(const std::string &key, const DataValue& value, const std::string &description="", const std::stringList &tags=std::stringList()))) Param p; p.setValue("key","value"); TEST_EQUAL(p.exists("key"), true) @@ -691,7 +703,7 @@ START_SECTION((void setValue(const String &key, const DataValue& value, const St TEST_EQUAL(p.getDescription("key"), "") TEST_EQUAL(p.hasTag("key","advanced"), false) - p.setValue("key","value","description",ListUtils::create("advanced")); + p.setValue("key","value","description",{"advanced"}); TEST_EQUAL(p.exists("key"), true) TEST_EQUAL(p.getValue("key"), "value") TEST_EQUAL(p.getDescription("key"), "description") @@ -708,7 +720,7 @@ START_SECTION((void setValue(const String &key, const DataValue& value, const St TEST_EQUAL(p.hasTag("key:key","advanced"), false) END_SECTION -START_SECTION((StringList getTags(const String& key) const)) +START_SECTION((std::vector getTags(const std::string& key) const)) Param p; TEST_EXCEPTION(Exception::ElementNotFound, p.getTags("key")) @@ -716,10 +728,10 @@ START_SECTION((StringList getTags(const String& key) const)) TEST_EQUAL(p.getTags("key").size(),0) END_SECTION -START_SECTION((void addTag(const String& key, const String& tag))) +START_SECTION((void addTag(const std::string& key, const std::string& tag))) Param p; TEST_EXCEPTION(Exception::ElementNotFound, p.addTag("key","bla")) - StringList error_list; + std::vector error_list; error_list.push_back("a,b"); TEST_EXCEPTION(Exception::ElementNotFound, p.addTags("key",error_list)) @@ -733,7 +745,7 @@ START_SECTION((void addTag(const String& key, const String& tag))) TEST_EQUAL(p.getTags("key").size(),2) END_SECTION -START_SECTION((bool hasTag(const String& key, const String& tag) const)) +START_SECTION((bool hasTag(const std::string& key, const std::string& tag) const)) Param p; TEST_EXCEPTION(Exception::ElementNotFound, p.hasTag("key","bla")) @@ -748,22 +760,22 @@ START_SECTION((bool hasTag(const String& key, const String& tag) const)) TEST_EQUAL(p.hasTag("key","advanced2"),true) END_SECTION -START_SECTION((void addTags(const String& key, const StringList& tags))) +START_SECTION((void addTags(const std::string& key, const std::vector& tags))) Param p; - TEST_EXCEPTION(Exception::ElementNotFound, p.addTags("key",StringList())) - StringList error_list; + TEST_EXCEPTION(Exception::ElementNotFound, p.addTags("key",std::vector())) + std::vector error_list; error_list.push_back("a,b"); TEST_EXCEPTION(Exception::ElementNotFound, p.addTags("key",error_list)) p.setValue("key","value"); TEST_EQUAL(p.hasTag("key","advanced"),false) TEST_EQUAL(p.hasTag("key","advanced2"),false) - p.addTags("key",ListUtils::create("advanced,advanced2")); + p.addTags("key",{"advanced","advanced2"}); TEST_EQUAL(p.hasTag("key","advanced"),true) TEST_EQUAL(p.hasTag("key","advanced2"),true) END_SECTION -START_SECTION((void clearTags(const String& key))) +START_SECTION((void clearTags(const std::string& key))) Param p; TEST_EXCEPTION(Exception::ElementNotFound, p.clearTags("key")) p.setValue("key","value"); @@ -814,7 +826,7 @@ START_SECTION((Size size() const)) TEST_EQUAL(p.size(), 4) END_SECTION -START_SECTION((void setSectionDescription(const String &key, const String &description))) +START_SECTION((void setSectionDescription(const std::string &key, const std::string &description))) Param p; p.setValue("test:test",47.1); @@ -850,7 +862,7 @@ START_SECTION([EXTRA](friend std::ostream& operator << (std::ostream& os, const TEST_EQUAL(ss.str(), "\"tree|key\" -> \"17.5\"\n") END_SECTION -START_SECTION((void insert(const String& prefix, const Param ¶m))) +START_SECTION((void insert(const std::string& prefix, const Param ¶m))) Param p; p.setValue("a",17,"intdesc"); p.setValue("n1:b",17.4f,"floatdesc"); @@ -869,7 +881,7 @@ START_SECTION((void insert(const String& prefix, const Param ¶m))) TEST_EQUAL(p2.getValue("prefixn1:c"), "test,test,test") TEST_STRING_EQUAL(p2.getDescription("prefixn1:c"), "stringdesc") TEST_REAL_SIMILAR(float(p2.getValue("prefixn2:d")), 17.5) - TEST_STRING_EQUAL(p2.getDescription("prefixn2:d"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("prefixn2:d"), "") TEST_EQUAL(p2.getSectionDescription("prefixn1"),"sectiondesc") p2.insert("",p); @@ -881,7 +893,7 @@ START_SECTION((void insert(const String& prefix, const Param ¶m))) TEST_EQUAL(p2.getValue("n1:c"), "test,test,test") TEST_STRING_EQUAL(p2.getDescription("n1:c"), "stringdesc") TEST_REAL_SIMILAR(float(p2.getValue("n2:d")), 17.5) - TEST_STRING_EQUAL(p2.getDescription("n2:d"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("n2:d"), "") TEST_EQUAL(p2.getSectionDescription("n1"),"sectiondesc") p2.insert("n3:",p); @@ -893,7 +905,7 @@ START_SECTION((void insert(const String& prefix, const Param ¶m))) TEST_EQUAL(p2.getValue("n3:n1:c"), "test,test,test") TEST_STRING_EQUAL(p2.getDescription("n3:n1:c"), "stringdesc") TEST_REAL_SIMILAR(float(p2.getValue("n3:n2:d")), 17.5) - TEST_STRING_EQUAL(p2.getDescription("n3:n2:d"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("n3:n2:d"), "") TEST_EQUAL(p2.getSectionDescription("n3:n1"),"sectiondesc") p.clear(); @@ -929,14 +941,14 @@ START_SECTION((Param(const Param& rhs))) TEST_EQUAL(Int(p2.getValue("test:int")), 17) TEST_STRING_EQUAL(p_src.getDescription("test:int"), "intdesc") TEST_REAL_SIMILAR(float(p2.getValue("test2:float")), 17.5) - TEST_STRING_EQUAL(p2.getDescription("test2:float"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("test2:float"), "") TEST_EQUAL(p2.getValue("test2:string"), "test2") - TEST_STRING_EQUAL(p2.getDescription("test2:string"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("test2:string"), "") TEST_EQUAL(Int(p2.getValue("test2:int")), 18) - TEST_STRING_EQUAL(p2.getDescription("test2:int"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("test2:int"), "") TEST_EQUAL(p2.getSectionDescription("test"),"sectiondesc") TEST_EQUAL(p2.getTags("test:float").size(), 3) - TEST_EQUAL(p2.getTags("test:float") == ListUtils::create("a,b,c"), true) + TEST_EQUAL(p2.getTags("test:float") == ListUtils::create("a,b,c"), true) END_SECTION START_SECTION((Param& operator = (const Param& rhs))) @@ -949,17 +961,17 @@ START_SECTION((Param& operator = (const Param& rhs))) TEST_EQUAL(Int(p2.getValue("test:int")), 17) TEST_STRING_EQUAL(p2.getDescription("test:int"), "intdesc") TEST_REAL_SIMILAR(float(p2.getValue("test2:float")), 17.5) - TEST_STRING_EQUAL(p2.getDescription("test2:float"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("test2:float"), "") TEST_EQUAL(p2.getValue("test2:string"), "test2") - TEST_STRING_EQUAL(p2.getDescription("test2:string"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("test2:string"), "") TEST_EQUAL(Int(p2.getValue("test2:int")), 18) - TEST_STRING_EQUAL(p2.getDescription("test2:int"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("test2:int"), "") TEST_EQUAL(p2.getSectionDescription("test"),"sectiondesc") TEST_EQUAL(p2.getTags("test:float").size(), 3) - TEST_EQUAL(p2.getTags("test:float") == ListUtils::create("a,b,c"), true) + TEST_EQUAL(p2.getTags("test:float") == ListUtils::create("a,b,c"), true) END_SECTION -START_SECTION((Param copy(const String &prefix, bool remove_prefix=false) const)) +START_SECTION((Param copy(const std::string &prefix, bool remove_prefix=false) const)) Param p2; p2 = p_src.copy("notthere:"); @@ -989,15 +1001,15 @@ START_SECTION((Param copy(const String &prefix, bool remove_prefix=false) const) TEST_EQUAL(Int(p2.getValue("test:int")), 17) TEST_STRING_EQUAL(p2.getDescription("test:int"), "intdesc") TEST_REAL_SIMILAR(float(p2.getValue("test2:float")), 17.5) - TEST_STRING_EQUAL(p2.getDescription("test2:float"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("test2:float"), "") TEST_EQUAL(p2.getValue("test2:string"), "test2") - TEST_STRING_EQUAL(p2.getDescription("test2:string"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("test2:string"), "") TEST_EQUAL(Int(p2.getValue("test2:int")), 18) - TEST_STRING_EQUAL(p2.getDescription("test2:int"), String::EMPTY) + TEST_STRING_EQUAL(p2.getDescription("test2:int"), "") TEST_EQUAL(p2.getSectionDescription("test"),"sectiondesc") END_SECTION -START_SECTION((void remove(const String& key))) +START_SECTION((void remove(const std::string& key))) Param p2(p_src); p2.setValue("test:string2","test,test"); @@ -1055,7 +1067,7 @@ START_SECTION((void remove(const String& key))) END_SECTION -START_SECTION((void removeAll(const String& prefix))) +START_SECTION((void removeAll(const std::string& prefix))) Param p2(p_src); p2.removeAll("test:float"); @@ -1111,7 +1123,7 @@ START_SECTION((bool operator == (const Param& rhs) const)) END_SECTION -START_SECTION((void setDefaults(const Param& defaults, const String& prefix="", bool showMessage=false))) +START_SECTION((void setDefaults(const Param& defaults, const std::string& prefix="", bool showMessage=false))) Param defaults; defaults.setValue("float",1.0f,"float"); defaults.setValue("float2",2.0f,"float2"); @@ -1119,8 +1131,8 @@ START_SECTION((void setDefaults(const Param& defaults, const String& prefix="", defaults.setValue("string2","default string2","string2"); defaults.setValue("PATH:onlyfordescription",45.2); - defaults.setValue("stringlist",ListUtils::create("a,b,c"),"stringlist"); - defaults.setValue("stringlist2",ListUtils::create("d,e,f"),"stringlist2"); + defaults.setValue("stringlist",std::vector{"a","b","c"},"stringlist"); + defaults.setValue("stringlist2",std::vector{"d","e","f"},"stringlist2"); defaults.setValue("intlist",ListUtils::create("1,2,3"),"intlist"); defaults.setValue("intlist2",ListUtils::create("11,22,33"),"intlist2"); defaults.setValue("doublelist",ListUtils::create("1.2,2.3"),"doublelist"); @@ -1132,8 +1144,8 @@ START_SECTION((void setDefaults(const Param& defaults, const String& prefix="", p2.setValue("float",-2.0f,"float"); p2.setValue("string","other string","string"); - p2.setValue("PATH:stringlist",ListUtils::create("d,a,v,i,d"),"PATH:stringlist"); - p2.setValue("stringlist",ListUtils::create("r,o,c,k,s"),"stringlist"); + p2.setValue("PATH:stringlist",std::vector{"d","a","v","i","d"},"PATH:stringlist"); + p2.setValue("stringlist",std::vector{"r","o","c","k","s"},"stringlist"); p2.setValue("PATH:intlist2",ListUtils::create("14,9"),"PATH:intlist2"); p2.setValue("intlist", ListUtils::create("16,9"),"intlist"); p2.setValue("PATH:doublelist2",ListUtils::create("6.66,6.16"),"PATH:doublelist2"); @@ -1153,10 +1165,10 @@ START_SECTION((void setDefaults(const Param& defaults, const String& prefix="", TEST_STRING_EQUAL(p2.getDescription("string2"),"string2"); TEST_STRING_EQUAL(p2.getSectionDescription("PATH"),"PATHdesc"); - TEST_EQUAL(p2.getValue("stringlist") == ListUtils::create("r,o,c,k,s"), true) + TEST_EQUAL(p2.getValue("stringlist") == ListUtils::create("r,o,c,k,s"), true) TEST_EQUAL(p2.getValue("intlist") == ListUtils::create("16,9"), true) TEST_EQUAL(p2.getValue("doublelist") == ListUtils::create("1.2,5.55"), true) - TEST_EQUAL(p2.getValue("stringlist2") == ListUtils::create("d,e,f"), true) + TEST_EQUAL(p2.getValue("stringlist2") == ListUtils::create("d,e,f"), true) TEST_EQUAL(p2.getValue("intlist2") == ListUtils::create("11,22,33"), true) TEST_EQUAL(p2.getValue("doublelist2") == ListUtils::create("11.22,22.33"), true) @@ -1176,7 +1188,7 @@ START_SECTION((void setDefaults(const Param& defaults, const String& prefix="", TEST_STRING_EQUAL(p2.getSectionDescription("PATH"),"PATHdesc"); TEST_STRING_EQUAL(p2.getSectionDescription("PATH:PATH"),"PATHdesc"); - TEST_EQUAL(p2.getValue("PATH:stringlist") == ListUtils::create("d,a,v,i,d"), true) + TEST_EQUAL(p2.getValue("PATH:stringlist") == ListUtils::create("d,a,v,i,d"), true) TEST_EQUAL(p2.getValue("PATH:intlist") == ListUtils::create("1,2,3"), true) TEST_EQUAL(p2.getValue("PATH:doublelist") == ListUtils::create("1.2,2.3"), true) @@ -1232,13 +1244,13 @@ command_line4[7] = a8; command_line4[8] = a9; command_line4[9] = a10; -START_SECTION((void parseCommandLine(const int argc, const char **argv, const String& prefix=""))) +START_SECTION((void parseCommandLine(const int argc, const char **argv, const std::string& prefix=""))) Param p2,p3; p2.parseCommandLine(9,command_line,"test4"); p3.setValue("test4:-a","av"); p3.setValue("test4:-b","bv"); p3.setValue("test4:-c","cv"); - p3.setValue("test4:misc",ListUtils::create("rv1,rv2")); + p3.setValue("test4:misc",std::vector{"rv1","rv2"}); TEST_EQUAL(p2==p3,true) Param p20,p30; @@ -1253,7 +1265,7 @@ START_SECTION((void parseCommandLine(const int argc, const char **argv, const St p300.setValue("test4:-a","-1.0"); p300.setValue("test4:-b","bv"); p300.setValue("test4:-c","cv"); - p300.setValue("test4:misc",ListUtils::create("rv1,rv2,-1.0")); + p300.setValue("test4:misc",std::vector{"rv1","rv2","-1.0"}); TEST_EQUAL(p200==p300,true) END_SECTION @@ -1279,9 +1291,9 @@ command_line_mult[6] = m7; command_line_mult[7] = m8; command_line_mult[8] = m9; -START_SECTION((void parseCommandLine(const int argc, const char **argv, const Map< String, String > &options_with_one_argument, const Map< String, String > &options_without_argument, const Map< String, String > &options_with_multiple_argument, const String &misc="misc", const String &unknown="unknown"))) +START_SECTION((void parseCommandLine(const int argc, const char **argv, const std::map< std::string, std::string > &options_with_one_argument, const std::map< std::string, std::string > &options_without_argument, const std::map< std::string, std::string > &options_with_multiple_argument, const std::string &misc="misc", const std::string &unknown="unknown"))) - Map with_one,without,with_multiple; + std::map with_one,without,with_multiple; with_one["-a"]="a"; with_one["-b"]="b"; with_one["-c"]="c"; @@ -1296,7 +1308,7 @@ START_SECTION((void parseCommandLine(const int argc, const char **argv, const Ma p3.setValue("a","-1.0"); p3.setValue("b","bv"); p3.setValue("c","cv"); - p3.setValue("misc_",ListUtils::create("rv1,rv2,-1.0")); + p3.setValue("misc_",std::vector{"rv1","rv2","-1.0"}); TEST_EQUAL(p2==p3,true) Param p4,p5; @@ -1304,7 +1316,7 @@ START_SECTION((void parseCommandLine(const int argc, const char **argv, const Ma p5.setValue("a","av"); p5.setValue("b","bv"); p5.setValue("c","cv"); - p5.setValue("misc_",ListUtils::create("rv1,rv2")); + p5.setValue("misc_",std::vector{"rv1","rv2"}); TEST_EQUAL(p4==p5,true) with_one.clear(); @@ -1315,8 +1327,8 @@ START_SECTION((void parseCommandLine(const int argc, const char **argv, const Ma p40.parseCommandLine(9,command_line,with_one,without,with_multiple,"misc__","unknown__"); p50.setValue("a","av"); p50.setValue("b","true"); - p50.setValue("misc__",ListUtils::create("bv,cv,rv1,rv2")); - p50.setValue("unknown__",ListUtils::create("-c")); + p50.setValue("misc__",std::vector{"bv","cv","rv1","rv2"}); + p50.setValue("unknown__",std::vector{"-c"}); TEST_EQUAL(p40==p50,true) TEST_EQUAL(p40,p50) //"executable -a av -b -c cv" @@ -1324,8 +1336,8 @@ START_SECTION((void parseCommandLine(const int argc, const char **argv, const Ma p400.parseCommandLine(6,command_line2,with_one,without,with_multiple,"misc__","unknown__"); p500.setValue("a","av"); p500.setValue("b","true"); - p500.setValue("misc__",ListUtils::create("cv")); - p500.setValue("unknown__",ListUtils::create("-c")); + p500.setValue("misc__",std::vector{"cv"}); + p500.setValue("unknown__",std::vector{"-c"}); TEST_EQUAL(p400==p500,true) //"executable -a -b -c cv rv1" @@ -1333,22 +1345,22 @@ START_SECTION((void parseCommandLine(const int argc, const char **argv, const Ma p4000.parseCommandLine(6,command_line3,with_one,without,with_multiple,"misc__","unknown__"); p5000.setValue("a",""); p5000.setValue("b","true"); - p5000.setValue("misc__",ListUtils::create("cv,rv1")); - p5000.setValue("unknown__",ListUtils::create("-c")); + p5000.setValue("misc__",std::vector{"cv","rv1"}); + p5000.setValue("unknown__",std::vector{"-c"}); TEST_EQUAL(p4000==p5000,true) // list options: Param p6,p7; p6.parseCommandLine(9,command_line_mult,with_one,without,with_multiple,"misc__","unkown__"); - p7.setValue("d",ListUtils::create("1.333,2.23,3")); - p7.setValue("e",ListUtils::create("4")); - p7.setValue("f",StringList()); - p7.setValue("g",StringList()); + p7.setValue("d",std::vector{"1.333","2.23","3"}); + p7.setValue("e",std::vector{"4"}); + p7.setValue("f",std::vector()); + p7.setValue("g",std::vector()); TEST_EQUAL(p6,p7); Param p8,p9; p9.parseCommandLine(4,command_line_mult,with_one,without,with_multiple,"misc__","unkown__"); - p8.setValue("d", ListUtils::create("1.333,2.23")); + p8.setValue("d", std::vector{"1.333","2.23"}); TEST_EQUAL(p9,p8); END_SECTION @@ -1361,8 +1373,8 @@ START_SECTION((void update(const Param& old_version, const bool add_unknown, Log common.setValue("string2","default string2","string2"); common.setValue("PATH:onlyfordescription",45.2); - common.setValue("stringlist",ListUtils::create("a,b,c"),"stringlist"); - common.setValue("stringlist2",ListUtils::create("d,e,f"),"stringlist2"); + common.setValue("stringlist",std::vector{"a","b","c"},"stringlist"); + common.setValue("stringlist2",std::vector{"d","e","f"},"stringlist2"); common.setValue("intlist",ListUtils::create("1,2,3"),"intlist"); // copy and alter @@ -1372,7 +1384,7 @@ START_SECTION((void update(const Param& old_version, const bool add_unknown, Log old.setValue("some:version","1.2","old version"); old.setValue("some:1:type","unlabeled","type"); old.setValue("some:type","unlabeled","type"); - old.setValue("stringlist2",ListUtils::create("d,e,f,altered"),"stringlist2"); // change some values, we expect them to show up after update() + old.setValue("stringlist2",std::vector{"d","e","f","altered"},"stringlist2"); // change some values, we expect them to show up after update() old.setValue("intlist",ListUtils::create("3"),"intlist"); Param defaults = common; @@ -1383,7 +1395,7 @@ START_SECTION((void update(const Param& old_version, const bool add_unknown, Log defaults.setValue("new_value",3,"new param not present in old"); Param expected = defaults; - expected.setValue("stringlist2",ListUtils::create("d,e,f,altered"),"stringlist2"); // change some values, we expect them to show up after update() + expected.setValue("stringlist2",std::vector{"d","e","f","altered"},"stringlist2"); // change some values, we expect them to show up after update() expected.setValue("intlist",ListUtils::create("3"),"intlist"); expected.setValue("some:type","unlabeled","type"); @@ -1451,7 +1463,7 @@ START_SECTION((void merge(const Param& toMerge))) } END_SECTION -START_SECTION((ParamIterator findFirst(const String &leaf) const )) +START_SECTION((ParamIterator findFirst(const std::string &leaf) const )) { Param p; p.setValue("a:b:leaf", "leaf_val1", "leaf 1"); @@ -1476,7 +1488,7 @@ START_SECTION((ParamIterator findFirst(const String &leaf) const )) } END_SECTION -START_SECTION((ParamIterator findNext(const String &leaf, const ParamIterator &start_leaf) const)) +START_SECTION((ParamIterator findNext(const std::string &leaf, const ParamIterator &start_leaf) const)) { Param p; p.setValue("a:b:leaf", "leaf_val1", "leaf 1"); @@ -1533,8 +1545,8 @@ START_SECTION((ParamIterator end() const)) TEST_EQUAL(it==p.end(),true) END_SECTION -START_SECTION((void setValidStrings(const String &key, const std::vector< String > &strings))) - vector strings; +START_SECTION((void setValidStrings(const std::string &key, const std::vector< std::string > &strings))) + vector strings; strings.push_back("bla"); Param d; d.setValue("ok","string"); @@ -1547,7 +1559,7 @@ START_SECTION((void setValidStrings(const String &key, const std::vector< String TEST_EXCEPTION(Exception::InvalidParameter, d.setValidStrings("ok",strings)) END_SECTION -START_SECTION((void setMinInt(const String &key, Int min))) +START_SECTION((void setMinInt(const std::string &key, Int min))) Param d; d.setValue("ok",4); d.setValue("dummy",5.5); @@ -1557,7 +1569,7 @@ START_SECTION((void setMinInt(const String &key, Int min))) TEST_EXCEPTION(Exception::ElementNotFound, d.setMinInt("dummy",4)) END_SECTION -START_SECTION((void setMaxInt(const String &key, Int max))) +START_SECTION((void setMaxInt(const std::string &key, Int max))) Param d; d.setValue("ok",4); d.setValue("dummy",5.5); @@ -1567,7 +1579,7 @@ START_SECTION((void setMaxInt(const String &key, Int max))) TEST_EXCEPTION(Exception::ElementNotFound, d.setMaxInt("dummy",4)) END_SECTION -START_SECTION((void setMinFloat(const String &key, double min))) +START_SECTION((void setMinFloat(const std::string &key, double min))) Param d; d.setValue("ok",4.5); d.setValue("dummy",4); @@ -1577,7 +1589,7 @@ START_SECTION((void setMinFloat(const String &key, double min))) TEST_EXCEPTION(Exception::ElementNotFound, d.setMinFloat("dummy",4.5)) END_SECTION -START_SECTION((void setMaxFloat(const String &key, double max))) +START_SECTION((void setMaxFloat(const std::string &key, double max))) Param d; d.setValue("ok",4.5); d.setValue("dummy",4); @@ -1596,9 +1608,9 @@ ostringstream os; OpenMS_Log_warn.remove(cout); OpenMS_Log_warn.insert(os); -START_SECTION((void checkDefaults(const String &name, const Param &defaults, const String& prefix="") const)) +START_SECTION((void checkDefaults(const std::string &name, const Param &defaults, const std::string& prefix="") const)) Param p,d; - p.setValue("string",String("bla"),"string"); + p.setValue("string",std::string("bla"),"string"); p.setValue("int",5,"int"); p.setValue("double",47.11,"double"); @@ -1613,7 +1625,7 @@ START_SECTION((void checkDefaults(const String &name, const Param &defaults, con TEST_EQUAL(os.str()=="",false) p.clear(); - p.setValue("pref:string",String("bla"),"pref:string"); + p.setValue("pref:string",std::string("bla"),"pref:string"); p.setValue("pref:int",5,"pref:int"); p.setValue("pref:double",47.11,"pref:double"); os.str(""); @@ -1627,10 +1639,7 @@ START_SECTION((void checkDefaults(const String &name, const Param &defaults, con TEST_EQUAL(os.str()=="",false) //check string restrictions - vector s_rest; - s_rest.push_back("a"); - s_rest.push_back("b"); - s_rest.push_back("c"); + vector s_rest = {"a","b","c"}; d.setValue("stringv","bla","desc"); d.setValidStrings("stringv", s_rest); p.clear(); @@ -1684,16 +1693,13 @@ START_SECTION((void checkDefaults(const String &name, const Param &defaults, con TEST_EXCEPTION(Exception::InvalidParameter,p.checkDefaults("Param_test",d,"")) //check list restrictions - vector s_rest1; - s_rest1.push_back("a"); - s_rest1.push_back("b"); - s_rest1.push_back("c"); - d.setValue("stringlist",ListUtils::create("aaa,abc,cab"),"desc"); + vector s_rest1 = {"a","b","c"}; + d.setValue("stringlist",std::vector{"aaa","abc","cab"},"desc"); d.setValidStrings("stringlist", s_rest); p.clear(); - p.setValue("stringlist",ListUtils::create("a,c")); + p.setValue("stringlist",std::vector{"a","c"}); p.checkDefaults("Param_test",d,""); - p.setValue("stringlist",ListUtils::create("aa,dd,cc")); + p.setValue("stringlist",std::vector{"aa","dd","cc"}); TEST_EXCEPTION(Exception::InvalidParameter,p.checkDefaults("Param_test",d,"")) diff --git a/src/tests/class_tests/openms/source/ParameterInformation_test.cpp b/src/tests/class_tests/openms/source/ParameterInformation_test.cpp index 691401d377d..1c419f86479 100644 --- a/src/tests/class_tests/openms/source/ParameterInformation_test.cpp +++ b/src/tests/class_tests/openms/source/ParameterInformation_test.cpp @@ -58,7 +58,7 @@ START_SECTION(ParameterInformation()) TEST_EQUAL(ptr->name, "") TEST_EQUAL(ptr->type, ParameterInformation::NONE) - TEST_EQUAL(ptr->default_value, DataValue()) + TEST_EQUAL(ptr->default_value, ParamValue()) TEST_EQUAL(ptr->description, "") TEST_EQUAL(ptr->argument, "") TEST_EQUAL(ptr->required, true) diff --git a/src/tests/class_tests/openms/source/SpectraMerger_test.cpp b/src/tests/class_tests/openms/source/SpectraMerger_test.cpp index 354c9fdab03..f0ec09ca7da 100644 --- a/src/tests/class_tests/openms/source/SpectraMerger_test.cpp +++ b/src/tests/class_tests/openms/source/SpectraMerger_test.cpp @@ -85,8 +85,8 @@ START_SECTION((template < typename MapType > void mergeSpectraBlockWise(MapType SpectraMerger merger; Param p; - p.setValue("mz_binning_width", 0.0001, "Max m/z distance of two peaks to be merged.", ListUtils::create("advanced")); - p.setValue("mz_binning_width_unit", "Da", "Unit in which the distance between two peaks is given.", ListUtils::create("advanced")); + p.setValue("mz_binning_width", 0.0001, "Max m/z distance of two peaks to be merged.", {"advanced"}); + p.setValue("mz_binning_width_unit", "Da", "Unit in which the distance between two peaks is given.", {"advanced"}); p.setValue("block_method:rt_block_size", 5); p.setValue("block_method:ms_levels", ListUtils::create("1")); @@ -122,9 +122,9 @@ START_SECTION((template < typename MapType > void mergeSpectraPrecursors(MapType TEST_EQUAL(exp.size(), 17) Param p; - p.setValue("mz_binning_width", 0.3, "Max m/z distance of two peaks to be merged.", ListUtils::create("advanced")); + p.setValue("mz_binning_width", 0.3, "Max m/z distance of two peaks to be merged.", {"advanced"}); - p.setValue("mz_binning_width_unit", "Da", "Unit in which the distance between two peaks is given.", ListUtils::create("advanced")); + p.setValue("mz_binning_width_unit", "Da", "Unit in which the distance between two peaks is given.", {"advanced"}); // same precursor MS/MS merging p.setValue("precursor_method:mz_tolerance", 10e-5, "Max m/z distance of the precursor entries of two spectra to be merged in [Da]."); @@ -154,14 +154,14 @@ START_SECTION((template < typename MapType > void averageGaussian(MapType &exp)) TEST_EQUAL(exp.size(), 28) Param p; - p.setValue("mz_binning_width", 0.0001, "Max m/z distance of two peaks to be merged.", ListUtils::create("advanced")); - p.setValue("mz_binning_width_unit", "Da", "Unit in which the distance between two peaks is given.", ListUtils::create("advanced")); + p.setValue("mz_binning_width", 0.0001, "Max m/z distance of two peaks to be merged.", {"advanced"}); + p.setValue("mz_binning_width_unit", "Da", "Unit in which the distance between two peaks is given.", {"advanced"}); // same precursor MS/MS merging p.setValue("average_gaussian:spectrum_type", "automatic", "Spectrum type of the MS level to be averaged"); p.setValue("average_gaussian:ms_level", 1, "Average spectra of this level. All other spectra remain unchanged."); p.setValue("average_gaussian:rt_FWHM", 5.0, "FWHM of Gauss curve in seconds to be averaged over."); - p.setValue("average_gaussian:cutoff", 0.01, "Intensity cutoff for Gaussian. The Gaussian RT profile decreases from 1 at its apex to 0 at infinity. Spectra for which the intensity of the Gaussian drops below the cutoff do not contribute to the average.", ListUtils::create("advanced")); + p.setValue("average_gaussian:cutoff", 0.01, "Intensity cutoff for Gaussian. The Gaussian RT profile decreases from 1 at its apex to 0 at infinity. Spectra for which the intensity of the Gaussian drops below the cutoff do not contribute to the average.", {"advanced"}); merger.setParameters(p); merger.average(exp,"gaussian"); @@ -187,14 +187,14 @@ START_SECTION((template < typename MapType > void averageGaussian(MapType &exp)) TEST_EQUAL(exp.size(), 28) Param p; - p.setValue("mz_binning_width", 0.0001, "Max m/z distance of two peaks to be merged.", ListUtils::create("advanced")); - p.setValue("mz_binning_width_unit", "Da", "Unit in which the distance between two peaks is given.", ListUtils::create("advanced")); + p.setValue("mz_binning_width", 0.0001, "Max m/z distance of two peaks to be merged.", {"advanced"}); + p.setValue("mz_binning_width_unit", "Da", "Unit in which the distance between two peaks is given.", {"advanced"}); // same precursor MS/MS merging p.setValue("average_gaussian:spectrum_type", "automatic", "Spectrum type of the MS level to be averaged"); p.setValue("average_gaussian:ms_level", 1, "Average spectra of this level. All other spectra remain unchanged."); p.setValue("average_gaussian:rt_FWHM", 5.0, "FWHM of Gauss curve in seconds to be averaged over."); - p.setValue("average_gaussian:cutoff", 0.01, "Intensity cutoff for Gaussian. The Gaussian RT profile decreases from 1 at its apex to 0 at infinity. Spectra for which the intensity of the Gaussian drops below the cutoff do not contribute to the average.", ListUtils::create("advanced")); + p.setValue("average_gaussian:cutoff", 0.01, "Intensity cutoff for Gaussian. The Gaussian RT profile decreases from 1 at its apex to 0 at infinity. Spectra for which the intensity of the Gaussian drops below the cutoff do not contribute to the average.", {"advanced"}); merger.setParameters(p); merger.average(exp,"gaussian"); diff --git a/src/tests/class_tests/openms/source/TIC_test.cpp b/src/tests/class_tests/openms/source/TIC_test.cpp index feb71784bc6..8b02558c9f2 100644 --- a/src/tests/class_tests/openms/source/TIC_test.cpp +++ b/src/tests/class_tests/openms/source/TIC_test.cpp @@ -70,28 +70,9 @@ START_SECTION(Status requires() const override) END_SECTION START_SECTION(void compute(const MSExperiment &exp, float bin_size)) - // very simple test ATM, since the computation is simply exp.getTIC(bin_size); + // very simple test ATM, check if compute returns an empty Result struct MSExperiment exp; - exp.setSpectra( { MSSpectrum() }); - TIC tic; - tic.compute(exp, 0); - auto r = tic.getResults(); - TEST_EQUAL(r.size(), 1); - ABORT_IF(r[0].size() != 1); // one intensity per input spectrum - ABORT_IF(r[0][0].getIntensity() != 0); // empty spectrum -END_SECTION - -START_SECTION(vector getResults() const) - NOT_TESTABLE // tested above -END_SECTION - -START_SECTION(void clear()) - TIC tic; - MSExperiment exp2; - tic.compute(exp2); - TEST_EQUAL(tic.getResults().empty(), false); - tic.clear(); - TEST_EQUAL(tic.getResults().empty(), true); + TEST_EQUAL(tic.compute(exp, 0) == TIC::Result(), true) END_SECTION ///////////////////////////////////////////////////////////// diff --git a/src/tests/class_tests/openms/source/TOPPBase_test.cpp b/src/tests/class_tests/openms/source/TOPPBase_test.cpp index 65c16dcb5b3..d70898eb3b9 100644 --- a/src/tests/class_tests/openms/source/TOPPBase_test.cpp +++ b/src/tests/class_tests/openms/source/TOPPBase_test.cpp @@ -523,7 +523,7 @@ START_SECTION(([EXTRA]String getStringOption_(const String& name) const)) p2.setValue("TOPPBaseTest:1:doubleoption",0.4711,"double description"); p2.setValue("TOPPBaseTest:1:intlist",ListUtils::create("1,2,3,4"),"intlist description"); p2.setValue("TOPPBaseTest:1:doublelist", ListUtils::create("0.4711,1.022,4.0"),"doubelist description"); - p2.setValue("TOPPBaseTest:1:stringlist", ListUtils::create("abc,def,ghi,jkl"),"stringlist description"); + p2.setValue("TOPPBaseTest:1:stringlist", std::vector{"abc","def","ghi","jkl"},"stringlist description"); p2.setValue("TOPPBaseTest:1:flag","false","flag description"); p2.setValue("TOPPBaseTest:1:log","","Name of log file (created only when specified)"); p2.setValue("TOPPBaseTest:1:debug",0,"Sets the debug level"); @@ -532,10 +532,8 @@ START_SECTION(([EXTRA]String getStringOption_(const String& name) const)) p2.setValue("TOPPBaseTest:1:force","false","Overwrite tool specific checks."); p2.setValue("TOPPBaseTest:1:test","false","Enables the test mode (needed for software testing only)"); //with restriction - p2.setValue("TOPPBaseTest:1:stringlist2", ListUtils::create("hopla,dude"),"stringlist with restrictions"); - vector rest; - rest.push_back("hopla"); - rest.push_back("dude"); + p2.setValue("TOPPBaseTest:1:stringlist2", std::vector{"hopla","dude"},"stringlist with restrictions"); + vector rest = {"hopla","dude"}; String stringlist2 = "TOPPBaseTest:1:stringlist2"; p2.setValidStrings(stringlist2,rest); String intlist2 = "TOPPBaseTest:1:intlist2"; @@ -752,11 +750,11 @@ START_SECTION(([EXTRA] const Param& getParam_())) test_param.setValue("param_int", 123, "param int description"); test_param.setValue("param_double", -4.56, "param double description"); test_param.setValue("param_string", "test", "param string description"); - test_param.setValue("param_stringlist", ListUtils::create("this,is,a,test"), "param stringlist description"); + test_param.setValue("param_stringlist", std::vector{"this","is","a","test"}, "param stringlist description"); test_param.setValue("param_intlist", ListUtils::create("7,-8,9"), "param intlist description"); test_param.setValue("param_doublelist", ListUtils::create("123,-4.56,0.789"), "param doublelist description"); test_param.setValue("param_flag", "true", "param flag description"); - test_param.setValidStrings("param_flag", ListUtils::create("true,false")); + test_param.setValidStrings("param_flag", {"true","false"}); TOPPBaseTestParam temp(test_param); Param result = temp.getParam(); // contains "test_param" + some default stuff diff --git a/src/tests/class_tests/openms_gui/source/GUI/TOPPView_test.cpp b/src/tests/class_tests/openms_gui/source/GUI/TOPPView_test.cpp index 01d32b1e03a..00b946bbc7c 100644 --- a/src/tests/class_tests/openms_gui/source/GUI/TOPPView_test.cpp +++ b/src/tests/class_tests/openms_gui/source/GUI/TOPPView_test.cpp @@ -124,7 +124,7 @@ void TestTOPPView::testGui() // register a GUI logger Factory::registerProduct(GUIProgressLoggerImpl::getProductName(), &GUIProgressLoggerImpl::create); - TOPPViewBase tv; + TOPPViewBase tv(TOPPViewBase::TOOL_SCAN::SKIP_SCAN); tv.show(); QApplication::processEvents(); diff --git a/src/tests/topp/CMakeLists.txt b/src/tests/topp/CMakeLists.txt index 2b0590ac1d4..6cada5f80cb 100644 --- a/src/tests/topp/CMakeLists.txt +++ b/src/tests/topp/CMakeLists.txt @@ -1994,16 +1994,6 @@ add_test("TOPP_RTPredict_5" ${TOPP_BIN_PATH}/RTPredict -test -in_id ${DATA_DIR_T add_test("TOPP_RTPredict_5_out1" ${DIFF} -in1 RTPredict_5_output.tmp -in2 ${DATA_DIR_TOPP}/RTPredict_5_output.txt ) set_tests_properties("TOPP_RTPredict_5_out1" PROPERTIES DEPENDS "TOPP_RTPredict_5") -#------------------------------------------------------------------------------ -# InspectAdapter tests -add_test("TOPP_InspectAdapter_1" ${TOPP_BIN_PATH}/InspectAdapter -test -ini ${DATA_DIR_TOPP}/InspectAdapter_1_parameters.ini -trie_dbs ${DATA_DIR_TOPP}/Inspect_FASTAFile_test2.trie -in ${DATA_DIR_TOPP}/Inspect.mzXML -dbs ${DATA_DIR_TOPP}/Inspect_FASTAFile_test.fasta -inspect_in -out InspectAdapter_2_output.tmp) -add_test("TOPP_InspectAdapter_1_out1" ${DIFF} -whitelist "spectra," "db," -in1 InspectAdapter_2_output.tmp -in2 ${DATA_DIR_TOPP}/InspectAdapter_2_output.inspect_in ) -set_tests_properties("TOPP_InspectAdapter_1_out1" PROPERTIES DEPENDS "TOPP_InspectAdapter_1") - -add_test("TOPP_InspectAdapter_2" ${TOPP_BIN_PATH}/InspectAdapter -test -ini ${DATA_DIR_TOPP}/InspectAdapter_1_parameters.ini -trie_dbs ${DATA_DIR_TOPP}/Inspect_FASTAFile_test2.trie -in ${DATA_DIR_TOPP}/Inspect.mzData -dbs ${DATA_DIR_TOPP}/Inspect_FASTAFile_test.fasta -inspect_in -out InspectAdapter_3_output.tmp) -add_test("TOPP_InspectAdapter_2_out1" ${DIFF} -whitelist "spectra," "db," -in1 InspectAdapter_3_output.tmp -in2 ${DATA_DIR_TOPP}/InspectAdapter_2_output.inspect_in ) -set_tests_properties("TOPP_InspectAdapter_2_out1" PROPERTIES DEPENDS "TOPP_InspectAdapter_2") - #------------------------------------------------------------------------------ # SeedListGenerator tests add_test("TOPP_SeedListGenerator_1" ${TOPP_BIN_PATH}/SeedListGenerator -test -in ${DATA_DIR_TOPP}/PepXMLFile_test.mzML -out SeedListGenerator_1_output.tmp) diff --git a/src/tests/topp/Inspect.mzData b/src/tests/topp/Inspect.mzData deleted file mode 100644 index 8fbf48d9cde..00000000000 --- a/src/tests/topp/Inspect.mzData +++ /dev/null @@ -1,435 +0,0 @@ - - - - - - - File_test_1.raw - - RAWData - - - FirstName LastName - - PHONE: +49-7071-123456 URI: http://www.OpenMS.de - - - - - - - - - - - - - - - - - - - - - - - - - - MS-X - 1.0 - none - - - - - - - - - - - - - - - - - - - - - - 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 - - - - - - - - - - - - - 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 - - - - - - - - - - - - - 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 - - - - - - - - - - - - - 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 - - - - - - - - - - - - - 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 - - - - - - - - - - - - - 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 - - - - - - - - - - - - - M7PKQw16zEMySs1DAL3NQ0E8zkObls5DutXOQ5E/z0OE189DMYjQQwAA0UPqkNFDgbzSQz+200MR69NDVjfUQ7S+1UNNHNZDP4XWQ+/s1kOLZtdDQevXQzMz2EP739hDAIDZQ2Zm2kOywdtD7v/bQ3DY3EOHid1DEVHeQ1Ia30PHxt9DHqDgQ8ZS4UPpWeRDETblQwSI50MC0+lDeJnqQ8XZ6kN6U+xD3zTtQzCH7UOuSe5DHPbuQyx070MoxO9DCljyQyQN9UPUXPVDpjr2Q0XH90MrY/hDgsf4Q1WN+kNVaPtDpov7QyDu/EPchv1DTmT+Q9s5/0Pv1v9DsqUAROHlAER+agFEkrABRC8xAkSOCwNE5V4DRNVvBURfmwVEZqYGRCrhBkTNDAdE5nAIRMS9CERm5ghEdxsJRHJeCUScmwlEHOUKRGmSC0SUYwxEEusMRASqDkTf6g5EZiYPRPSuD0SQFhBEZqYQRIbyEETseBFEvPIRREkTEkR/JxJEvVoSRJIHE0SUJxNEUV0TRGamE0Sa2RNEAEAURHyqFESo9hREwwwVRCarFURkKBZEcG0WRClcF0TruBdEEaAYROpgGURN5hlEjngbRGYeHERmJh1E2ZIdRF1bHkSamR5EkfseREZzH0Rmph9E+t4fRNgeIER4SCFEWbIhRAAAIkRoHiNEHTQjRMZ9I0QGqyNE1SIkRBLmJERRHiVEumElRKSpJUT19SVEVGgmRDaeJkRk1CZEUvYmRJrZJ0SrKihENnUoRNu3KET0fClEeLcpROQCKkSaWSpEzAorRDQzK0SNVS1EZuYtRP49L0SoQzFEgvYxRGgzMkRzajNEhuszRDQzNUSrqjVEpNE1RP46N0R5TzdE3J43RBHeN0SYzDhE7E85RADAOUQA+DpEUDc8RCyEPET0QT1EAkI+RIarPkRKyD9EYu4/RKJlQETfwUBE9SxBRMReQUTC1UFEOkZCRNTRQkSa2UNEzQxERFacREQB6URE9A5FRPpoRUR20EVERtdGROkCSEQwtUhEIHZJRDHfSUTOYkpEzVxLRJjbS0TNDExEWEdMRH7dTERmDE1EYo1NROk0TkSuNU9ESm9PRM6MT0Rmxk9EZuZPRLxGUERU8VBEztJRRGL1UUTAvVRErOhURFBkVUSl3lVEMlVWRJ7fVkTAIVdEAEBXRGamWETCk1lE9BlbRHppW0SkrFtEbVJcRFXoXESa2V1E3ENeRJgFX0SeS19EvNtfRBwQYESoA2FEAIBhRB5PYkS0j2JEWZtjRNNRZEQxyGREtzZlRLOXZUTDs2VEaWtmRAPrZkSuRGdEmploRO1laUQkL2pEJ5NqRDfeakRrUmtEaQJuRAAAcER3m3BEpapxRJpZdEQXiHVEZ+Z2REHed0RbUXtEq6KARGo1gUTkjYFE4xuDRN41g0S8zYNEJCmERHpChEQckYhE5VqJROJtjESXL5FE2OOVRO3NlkSFdJlE9qicRAjVnETq4J1EaimlRBC8pkQ= - - - FdiwQeyXAkQNgv9CpLEsRCo5CUT4UGJEx7V4Q2AjJ0IwfjhCXNwRQhBf40H2rsJD2k2uQ3KGf0LHufZBXRF8QyNCpkOL7r5CarHnQv3xTUPcgwxD5XTuQt3yzUHwaM1DxRvKQU+WDULNK91BGxMGQqNeCkODGJVDOLeAQjfErUJj55ZCh7EsQ5hQmEKYyDxDRhQGQ4qxrEN5lg1C2i66QprIYkJTXUVCjn3mQrbgEUNxOMNCrtF+QjctR0LH0h9Dw5A5Q40hp0MVIQlDmvrrQsm7D0M8QeFCLodWQu2XskO5ozpDr5U+Qtb7AETzRHBCkYLHQ7aGVkIU8k1CozkIQ9wBhUM89lxDIAaUQ7791UNKT1NDTFAYQ9cLI0Jqp8lCA1/jQY1d/kGZQxFCAgzIQz323EOsDgVCPHhkQ+m/HkL20FpCTEImQ/NYNkOkL6VC37+eQv/aPUPOJodCWL3WQbOxLEOrlo1CUaL8QSfAHkO1p0lC1HELQ/obAEP/USdDwnmpQoeMj0IXh49ClgGFQud5vUGHhtZBdjakQcDZeEMGosdCnhBvQt/xTUQUzhBDBi4ARP4qFkKlp0lCr/ehQ388UkI/n6tDVjzSQqAiC0J4RPBBdzoNQ8EFFENflJdBqJOjQ5EET0NFHN9BtoZWQokOskJ49lxD9uCRQubyCkJKdyBDmKG5QqJeRUIM0dpC/WVjQywTwUJ7cNxBS+yZQ/DkoEJ+cYtCC2ryQv0mEUIeOKFCQOV+Q0KnSUJpdRpC3dBaQt9e/0FcaXhCx7kuQrr+ekNQVCdC26H1Q2EN7kH0KVFDHKIEQhjAnkOFrY9COK2dQ9a/nkJeh9ZCLp8QQvnyCkIqWv1CN4CNQmQLd0PCq8NC5NmhQiN+OELNGJVD5Z4rQ4UzNEIJnytCE1UjQjVdxUJ7QOFCuskBQw2fK0I449tBMYgbQwrKAUOD7b5C3+mvQtN5qUKPiS9C40SQQxp+OENd8s1BWL3WQYmQCURrdNJCW2FUQ1YKI0P5N8NC1XH7QQvOEERgnYZDe9mYQxe5pUPogwxDpTolQtYSwUK48gpCf9yCQnRib0PL+x9DUsi8QnbZeEMli+VCR9qdQoBIv0EMmJtCA5GZQbPtPkPw4BFDqffqQZXgkULGFOZDHFa2Qomw50JTlg1CityCQpmxLEPFzWND6srfQTZ1GkJPXUVC5EuJQ7RlY0MycQtDOY+UQ51l40JQNqRBuyaHQiMhM0P4/ppDo6dJQ4qCx0JSG19DeRvKQcoFFENavllDM5aNQsZ5qUL9wmhDvRwkQ8LDb0PttABD6SQFQi5dRUNqG19CmJSXQdIBhUKF6S9C/KgOQ8rJgUOsmhxDw1g2Q5iUl0E1eGRDP5lXQ+pe40Hh2fhCmJSXQd9e/0EGJH1CdnUaQlMxF0Jkp0lC7p4iQtusCkK+8U1CcUn/QqmFM0KvG19Cb6fJQkEvpUJc6S9DFZ8rQts3w0L/FtBCHJ8QQo1A4ULUN8NCf//DQSZxi0I= - - - - - - - - - - - - - 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 - - - - - - - - - - - - - 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 - - - - - - - - - - - - - 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 - - - - - - - - - - - - - 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 - - - - - - - - - - - - - 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 - - - - - - - - - - - - - - - - - - - - - - - EqNWQ+7AYUOtrmJDpthjQwAAZUNi425DMO9vQ1K4c0OB+nVDmpl2Q7C4eUMkpntDmm2AQ5D3gEMzb4JDZd2CQ4uFiEMAgIlDnXeNQ/gOkEMwVZJDilSTQ3pslEMlhZZDWgWXQ7ftl0O6XZ1DzcyeQ4KCn0OhVaFDAICiQz7tpUMVeaZDntOmQ81sp0Oq7KdD9m2oQ81MqUN8gLBDzIixQ9fssUNGhbRDt+20QzDwtUM8X7dD9Sq5QwCAuUPU8L1D+Gy+Qyz9xkMmbcdD2mHMQ5bIzUOpFc9DKZjPQ7z0z0MsHdBDVavQQ1TF0kN8adRD3vnVQ/E91kMO1NZDzUzYQ81M20OK0NxDr+vmQ6RAOkQ= - - - ipocQ2gk/ULIzMtDnZr8Q6h5vUGw41tD8L+eQqZhVEPYfZBD70NWQU4RIkIgPFJC4Z4rQ+/JAUQmTIlCyuecQvgW0ELZ8gpC5Nl4QpQYFUON2XhC8H04QmFhVEPM52pDarsPQ9JE8EIVTAlD7RrfQdBk7kS92XhC+fIKQh5nqEMG3QJDa3UaQ3Z1GkIqt4BDYNyCQ76Ul0GqfJNDhfnGQ9YFlEMH4RFChzMkQqjtPkOS6a9CPI9ERHmd7EF0OThEX9IfQx/aeEMXxK1CJI5PRIzEC0NUyyZEslqnQtZ2Q0PyrDtDAyeHRIbcAkOuRHBD0mGPQj2ODUMltwBDDL3WQSo2pEEm8xJDqiYHQ/cqFkM= - - - - - - - - - - - - - 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 - - - - - - - - - - - - - - - - - - - - - - - IoJPQxS7VEMx7lhDjrlaQ9HoZkM+12dD3LNoQ+QLdkOAhYFD/HWDQxCFhUMzM4dDrZaIQ/5TiUMX2oxDM+mNQ+mJj0MF7JBDE3ORQ9tSkkMh05JDrwSUQ5V5lEM7uJRDIOiUQ+p+lUOHmZVDPhWWQ+ODlkNQIZpDmRCbQ/ZinEPa5ZxD11edQ/jxnUN6HqFDqYWjQ3IqpUMk/qdD9teuQ9IRsUPZuLRDwVS1Q4b9tUMU6bhDmHa5Q+CHvENmZsFDd93CQxkLxEP4gMVD2J7FQwd3yUPkvMpDMVfLQzZfzEOmU81DyjjRQwhT00Ng5d5DcorxQ9Q/IkRMPSlE8E8qRA== - - - GPJNQlgxF0KuuAVCWQojQ/xlY0JgCiNDd9wCQ9IFlEMJzhBDZF1FQuM3w0KGG8pBnNwCQ6O4pUOOnYZDX3RVQ/GEM0Jn6S9CJazYQk6Cx0IOzpBDTuqvQve+2UPj0gFDQ82ZQtW2jENz3MRCW84QQ06qA0R1DrJCgDzSQqLSH0SqHslDFkVwQuO/nkO5JodCXBvfQucztEIMJ4dCs1QnQjpF8EKn4BFDP/bcQjIGlEJqu49CnTxSQsxEkEM72LBB86wlQ6th1EMvGgZEbfqQQrkb30LXH+5C/qvYQqE80kJBUBhD1U5TQ8u/HkNG2nhCSFNiQ0pZNkPzG19CXDxSQg== - - - - - - - - - - - - - - - - - - - - - - - z7NQQ83MVEPWqVVD05FWQ+/uWEORLVpDvuZhQyu1Y0Pk6mlDE+RuQxv+b0NWCnFDxthxQ0Acc0MK63NDFtJ0Q67sdUNX635DLl6AQ+PugEM87IJDYXKDQyf1hENb9oZDjFKHQwDSiUO6VIpDxGyMQzmOjUOrUo5DQXCTQ6SFlEO+CpVDZjmWQ5J0l0MfHZhD4Z6ZQ9xgnEP89ZxDi2ydQ2dhnkM93p5DZH2fQx62n0Ocb6ZDtFinQ7UDqEPdXahD7xCpQ4ydqUN4MqpDIJ+xQ/R2tENK57RDoQi5Q7AFukMiebpDxSC9Q96FvUMWD75DMBPCQ4hbwkPYm8JDnAzGQ6Z+xkOaB8dDHnrHQ+JczENx/M5DGU3PQ/aNz0Mu9M9DLYbQQ9xi0kP4dtVDENjfQ1ad4EPs0eFDBB0IRM1MNUQ= - - - XW+4QqR6IkJlCzRC0QW/QqeFjEIAuPNCkqykQpKIH0JT1gRDTgQHQg6GjEJxSKBD3bjXQzu0/kE3ThVDA2ITRFu9aELo6ZBCHidiQy/GF0SudK1CMj02QyeLgULogZdC0WaWQ2iFjEJyRVhDZUVYQ4DCJUIdyFJCsFOKRCRvOEMmpAJDsVssQ9PpdUK/pi9DOvrUQsXM40Mynw1CTLPiQ+SQ20MmQGNDb3cRRa9vDUNO3xhEK6SCQ2NRwkNEthFECmcWQ3mpXEM+gJdDoPTfQleLZkPcpq9CHuQbRFkXHkJTvYNDKtgbQplpw0O9ZwhE8GoxQ6rBSkMMsyJDV6SCQ4fAxUNsHBNDLKkFRN9CK0PP/CVEkDT1QxuQKEOs7+pCOqE6Q2wWnkKCDVJCCYIZQgPIUkJmkFtCmJtFQh6Q20E= - - - - - - - - - - - - - - - - - - - - - - - OsBUQ3lzWEO6pVpDKLtdQ+jnXkNwpGFDHcNiQw65ZkN54W9DOu1wQw7Te0Np635DJuN/Q+HzgEPheYFDzWyFQ4XrhkPA7odD52SIQ6LqiUPEP4tDxwKMQy3tjkPHB5VDTHuiQ0edokPPEKNDAAClQ2Kdq0PyB6xDDLWtQ+wCrkOohLFDZua1Qx0HuENkTbhDqoa5QysSvUMKd71DZAXBQ/dsw0OQG8ZDilvOQ1H7zkOokM9DSAfRQ8bX00OaodhDnKjdQ7bo3UNmZt9DMNniQxWU5kPNTPBDYaTyQ3obAUTMxgFEjJEERM2MB0SceAlE4AEKRMhnEESqXhlEhORPRIR6gUQ= - - - sY90Qn6nyUIhCiNC/TDKQ4D/w0EKukpDFcAeQqcOMkNS85JD7g8uQp2DDEMUT1NDJs4QQwckHURInMFDlDolQjC3gEJW6a9DjrcAQhlxi0PS+mtCzmVjQ8vgEULwrsJDrRiDQ11BUEPdQOFDuBvKQaXSH0M1sOdC0D33Q8HmZkJz+utC20MRQtLRGUMwbHZBRvMSRCUCBUJJnytCLgqjQpVUp0Jl3OJDH5c+QphGNUNVdFVDxhLBQzorFkL+S4lCXj0GQ67vEEOBAQVCtAGFQptx60PKlJdBNYLbQfDkoEIOd79DnwEFQ/N5vUE8F9BC8OSgQlzIPEMG8s1CaCGzQ4JA4UI= - - - - - - - - - - - - - 3w3KQzKMykO5/8pDAIDLQ7cUzEMoTMxDTnvMQ+zozEOHKM1D2o7NQ7MLzkP8fs5DuvfOQ8FPz0O5ec9D2t3PQwUr0EMTbdBDrPrQQ9It0UOlbdFDWgbSQzBu0kMnv9JDoW7TQzoF1EMHTtRDvRfVQxmH1UPWydVDkgLWQ6xy1kNVC9dDPF7XQ/ir10PYHthD5JXYQ/Mb2UNElNlDQuDZQwFS2kO+rtpD/grbQ4NN20Ohk9tDpxbcQ5yI3ENnuNxDqSjdQ+t23UOgL95DwozeQ/cb30Mcb99DRevfQ6Yr4EMOnOBD4QbhQ4B24UOe2OFDlRbiQ1xj4kMBx+JDRwbjQ0dT40NpiuNDcw7kQ1lq5EMAy+RDERDlQ5Bx5UPQoeVDNBbmQ0hp5kMn4+ZDoRPnQ4l+50MIoudDoPTnQyV/6EOyFelDNnzpQ5nj6UNFZepDc7XqQ1QV60OQZetDiaPrQ/cU7EPEaexDyqvsQ0QZ7UOSWe1DuJTtQzz77UMzJu5DInXuQ0Tx7kN2Ie9DcXvvQ/jw70OiTvBDbMvwQ70Q8UPIZPFDpJLxQ+4O8kPMf/JDrcfyQ8sg80NddPND/KbzQxEg9EPrbfRDe6H0Q6kD9UMeL/VDanz1Q+rU9UN+PPZDFFL2Q5iN9kMY1PZDGEL3Q6Bx90Mcr/dDxOv3Q7ty+EO0wfhDgCT5Q4Z1+UO0y/lD4ST6Q5Ju+kO3q/pDjQj7Q1+H+0NotPtDiz/8Qx56/EONxPxDgxL9Q/GQ/UO0Af5Du2z+Q3ei/kPZDf9DWoX/Q7C1/0PlHABE5zsARO9eAESijwBELb0ARCz4AEQ5DAFEySMBRJhTAURPigFEUrYBRG3UAUSx8QFEGCoCRMZSAkS+gAJEoI8CRCLEAkRWDANEDC4DRPRWA0TuiANEyKoDRMPRA0TFCAREfiwERABiBER8jQREc7IERBbZBEQv7wRExRUFRKRDBUQZVAVEUI0FRF6rBUR24wVEFgMGRHAxBkSJjAZExrcGRE3WBkTSAAdEQCUHRCxPB0QIfAdE2ZkHRJW3B0T8DghEiEUIRHqACEQgkghEedgIRL37CET+IglEU2sJRDKGCUTIrglEkM4JRNgOCkRuKQpENEIKRHp0CkTGngpEQL8KRNfuCkSmJQtEyWoLRBeLC0QgrwtEcOULROsQDERFUAxE9owMRPSsDETQ/QxEWzANRIZjDUTyhA1EY6sNRMPlDUQ5Cg5ECzYORJxNDkTHiQ5ELKQORLHIDkRV+A5EqxcPRBQ8D0TaUQ9E+YcPRDu/D0Qs4Q9EBBIQRFdQEETFhRBEjqUQRNy4EER79hBEQg0RREBBEUROVhFENIwRRNK9EUS71RFE7BASRGVHEkQuexJEMpYSRC/jEkTGBRNEEX8TRISSE0TuxxNEBAUURMotFESQZxREpKEURAjTFET8DhVEXzkVRC5UFUTffxVEBbcVRFntFUTpCRZEGj0WRKZgFkTyoRZE4MQWRDjWFkRdDRdEwRwXROo/F0QMbRdET5wXRPW7F0T63hdEEvcXRFlFGES8fRhEiqMYRFy+GEQK7xhEBA4ZREooGUS6UxlEHocZRMywGUQ40xlE6f4ZRDwlGkQaPBpEbHMaRIanGkT33RpEPe4aRPb/GkRCQBtEjWUbRNOCG0SnxRtEM/MbROY6HETWZxxEsYUcRJOrHEQr1RxEs/UcRNIrHUThYB1E1J8dREbFHURGAB5ELx8eRPZYHkQkax5EbZgeRC+0HkTbzR5EkfseRJ41H0RUdR9E1qAfRI/HH0Ty9B9EGjkgRJpFIEQWhiBEf6ggREQBIUROLSFEeFUhRJ+PIUTouCFEOvghRMgyIkRAWyJEEIciRNKsIkTL5CJESiwjRJY1I0SCSyNENowjROi3I0Tu0CNEVhckRBYtJES6gyREtqAkRB7EJERo+yRE+BUlRHY2JUSOYSVEtpAlRKi/JUS9+CVEGjUmRM5LJkTqgyZEerYmRL7JJkTkAidEZkEnRCKXJ0TgxidExOUnRHgFKERcKShElG8oRGCVKEQAvihEs+goRDD3KEQSNylEcFIpRJiFKUQWkilEgL4pRCIBKkQCGSpETk0qRApcKkQKhypEDKwqRNDTKkTo/ypEiRcrRHI3K0RyfStE0qArRPTNK0Tw9StEajAsRKZGLERieCxESLAsRFLQLESSBi1ETh8tRPBhLUS2jC1EeactRNrKLUSA/S1EmhMuRFQ/LkQQaC5EtosuRKbELkRp+C5EtiMvRIxrL0TqqS9EkeUvRGwQMESKQTBEWVMwRPx/MER0rTBErNYwRIoCMUSoFTFETDMxRHpRMURgbjFES6UxRCXFMUTe4TFE7gIyRPQxMkSaUTJEMHQyRAKfMkTo0TJEk/oyRNgsM0S0WjNEqH8zRJq9M0R38TNE3RQ0RDxYNEQedDRELKs0RNQHNUQhMDVEIGw1RNicNUS2qDVEOes1RBwENkRgSjZEnW42RLqoNkS6IDdEslo3RC56N0SprDdE7OI3RDMkOEQiXjhEznc4RHOaOEQavDhEr9s4RO36OESrKTlEx085RLyFOUTSqDlEv8c5ROj1OUTAYDpEuaU6RCziOkTBKDtECzM7RJCDO0SIqztEBNQ7RKb1O0RwFzxE3k08RFpfPESUpDxEhMc8RPz2PEQKLD1E8209RP2lPUQMyD1ET+Y9RKgHPkScNT5EgHg+RPSRPkRNtT5EtN0+ROoSP0QTOz9ExFs/RLSFP0To/z9EVT5ARMpmQESer0BEmAJBRPI2QUQ/WEFET4FBRF6jQUR0yEFEJBFCRAAnQkTEh0JEuLdCRPXiQkRyGUNEFVJDRM2UQ0RUwENE5v1DRPUYRERKLEREWFRERLB4RERYk0REfMxEREL+RETeHEVEjH9FRE+bRUSZzkVElOdFRBwWRkR/T0ZE8m9GRKSRRkQQrkZEyNVGRMD5RkQkH0dE1EZHRAJcR0RIikdEHqdHRNbaR0T6C0hELClIRLBMSERQtUhExPlIRIIeSUTORElEEXJJRCShSURJEkpExSFKRPw6SkTPX0pEOoFKRLCkSkSw1EpEWAZLRJYmS0SqRUtEYYpLRNrNS0SK/UtEZhhMRBI3TERgY0xE3oNMRI6tTESo7UxE7R9NRAZETUSocU1Ehp9NRKrlTURmG05EXGlORCaFTkRUt05EKNdORFb5TkTSI09E4UdPRMFcT0RImE9E6btPRIjpT0REDFBEYidQRLRIUEToXVBECdBQROT1UES8EVFE7lFRRNJ3UUTGoFFEOLpRRJbpUUQ0RVJE1V1SRCSbUkTKy1JEtgFTRB1SU0QIdVNErJdTRBq1U0QY8VNE3A1URAhEVERlfVREzcxURB0PVURAPVVEgWJVRASqVUTm4lVEthFWRFQqVkRWpVZEAPZWRMYgV0QVRldEgHlXRLaZV0RyuVdETN9XRGwZWESgRlhEHHpYRJmkWESi3FhEHCJZROVLWUSAb1lEmKRZRAnQWUSq+FlE7S9aRPBRWkTye1pEFq1aRHrWWkSoTFtE1IRbROG4W0SU8VtEMh1cRG0pXESAolxE4rpcRKraXEQ6/lxERFddRJh1XUTq+l1E0BpeRKxPXkRmkF5E6qReRBLHXkRO4V5EqBpfRP5mX0TWmF9EBv9fRFwfYERNX2BE8P5gRJBKYUSyZ2FE+ZthRKr1YUSGF2JEAEBiRP6JYkTWsGJE9uNiRPpDY0QceGNE0rNjRH9DZESBkGREMqFkRPgBZUTuLGVE55VlREeyZUQXAmZEGyRmRE9BZkTopWZEF8NmRGsaZ0RDN2dEkIRnRNXWZ0QDHGhEe0poROdnaEQRpGhE28VoRNH0aESPNGlE19FpRFH8aUQ8nWpEMzNrRKyJa0RnpmtEdOVrRHc4bEQkdWxEX+5sRAMCbUQbdW1EMwBuRKNSbkT3eG5ExpBuROvDbkRDB29E509vRHbhb0SOIHBEf2FwRFyMcEQSq3BEycFwRJoZcURiZXFEBqRxRMHlcUTVEXJEUSpyRMWRckRQGHNEl15zRGqKc0T8CHREwxt0RPtCdEQmgnREH+d0RF6fdUSeznVEkxV2RMU0dkQGfXZEmKR2RD0Cd0QIZHdE3Il3RBKrd0SixndEvBJ4REM1eETwmnhEJgh5REpheUQhdHlEPZx5RFzEeUSWOnpEv1t6RHGSekSF63pEcjd7RMdbe0Slk3tE27J7RJPxe0RxbnxElZZ8RA+yfERf6nxE4A59RK9jfURBnX1Ex+99RGcmfkQAgH5Es+V+RKduf0QKEYBEdjqARM1sgESgjIBEzsiARNoNgUTEg4FE/KiBRL32gUQII4JEWEuCRHKBgkTUt4JEPMyCRC3tgkQW+oJEfBqDRKiag0RQ5INEDviDRBwAhETWN4RE1lqERCGVhET8n4REUraERMj7hER3aYVE5qCFRLy6hUQQ5oVEHgyGRPY4hkTGT4ZEJLGGRM3MhkRtSYdEAGCHRD3Ph0To6IdEGmKIRF6HiESCzYhEldmIROHtiETQFIlEajWJRGyHiURApIlEss6JREgIikQ0M4pEeP+KROgHi0S+VYtENHSLRP+9i0SoG4xEHEmMRM2MjEQA4IxEsE2NRJp5jUTNqI1EGNSNREQCjkQShY5EjPqORNIgj0QuoY9ElOePRCo2kESU1ZBEzU2RRACUkURmBpJEklSSRKzHkkTq/JJEBl2TRCrJk0TNbJREBJ2URMztlESEWpVE0pSWRJr5lkQSP5dEyq6XRNJ9mEQi9JhE4YSZRH4SmkRmxppEDEGcRDQznURmhp1EUsSdRPrWnkRmz59Ews6gRJQHo0RgfKVExC2pRO6AqkTQsKpEgsmqRLhirUTcIK9E8M2yRAv2uUQ= - - - nMFSRiYysUXFwP5EUL4iQ21ECER48yhFLXafRJDozEMTO3FFpSscRazCsUU3VZRFaCM1REIaTkV5DGVEf2OZRJpwWUWcC5tEOyEfRa4wnkTpLoZE6F+dROCPW0XcTRNEPZIbRa77mUMc8p1EoC0iRoELYkV0cBBFcRO3RKJIHkSScAlF9N5KRW71yUTJX8pGU/MiRg0oh0budVdFB2HERIQG3kXILBNFrzUmRdqzbUV9rAFFuRc5RZhD7EM6Ap9DWnuwRakoBkXkxdlE+VtmRXh+OkX6jaVEDG8pRZ8Xn0Z8mA5GCbBaRcCoZ0UCs69ENhQFRXVV7kQ1wxFEBoBhRZ1NBEVL5mBEmWtfRcq/e0RrSI5EPLKDRPFKNUXtlKxEvoKhREYq3EMpv5REy+95Rk/660R/IPBDY8adRIfUUETDT/pE3gXQRcBYtkSbNtBEm3Q/RG0O8kWoTgxFAITLRFe37UM8TZ5Eln0oRXFrQUVamFZEUQeQRZkLiEXRMadEfFXIRI9aR0VaMcFEGPEeRD82jESEcT9DvfMHRRb/EEVxewtFSJVVRKQTDEWYslBF56yHROQ0B0WXTXhFS+VyRcttvkRiVJlFaMHqRMCJhEUPcUxEnxybRIySFUVeTIJEXUgUROfOjUS/2s1EJouNRKAlkUMonGVDPzWSROesiEXajTtFaHafROAexkTAWu1DdJJ4RbRhSkWRARJF3VvfRIEYKEXWUlZFxBa3RN1ySEX87p9ERQ6hRGfCgkWVUnFEOgprRfVR9kWYoI5FN+8DRWoYHUXiTydF0f4ERTxVS0SjI9JEDda2RJwqD0UgkpRFH9wqRb3vh0WlH0ZFNDYKRZ3fHkV4A4JERh5RRdG7o0MaerFFCPnLRa+qnUTDTo1FMvnARFRTrUQTxRlFK4e/Q/eKwESmh2JE5qzTRPLjfkRKI6FExfw2RX/uR0T5F+xD7jJgRTc630Q9i5VEGQT8RJubKUVcHSJEdFocRCbWnkTbKu5ESnHYRDWnSkQGUi9Fcn1+RS+QBkWiwi5FqUlcRKXA3UQ+TAFGYCkVRUxZjUVDSpFF4xwLRQLNj0R4q0hEHMucRPoKhUSgMOVEDgO2Q2WLi0SL/ltD5NbrQ7X3ZURGZE1EEY7pRN/r70P4/RJF9QSFQ9jSKETZQ0dE4JaXRMETcEYOS8tFTAkFRc1nNUUXVEtFGi4xRGYpZ0QKLGlF9FkMRazhaUTDBKpFgAFiRJEZIUTITQ9Ex2U8RRbRu0RQeYlFKSwYRggOPEW7aehDeOPhRHZU4kS8+h5EOA6KRQPCbEXsEElEED4TRcv2XUTTDOxDeeaKQ8ebhkU3PF1EmrPuRZwdiUQhraNDsNjPRZLMF0WFg9RDjGE8RAP140MDLRVF2x9vRXy3oUUL7D5FiFH9RNFA4URYrLxDd35XRWjPoETaJZpEflhuRCSnHERabRNF2IMBReeVcURvfGBEGOKIRHCzMEXT6sJEwG9XRSuUyUN8YC9FmkM5Q5P3z0QrYMdEnMG3ReIdhEVLI6hEvch0RIujwESeNyBF+5YHRfEB+EM4OfhEktEsRYiGu0QWlf9EooUdRCnmwUQiOs5DwaUsRew8tETX8cNDT7hsRYECTEQNFoBEhPl6RNlv0kOW801FdyadREcIWUQaV/REuU7sQr3g4UNCyNxEnB4tRVl1lUQ6kj9EgIC6Q38yPUV0pEREB1KJRCpzhkTcRwRFvHvARTM+YEX9HvtDRQU/RU2IfkRRpUVEq8MzRO8UrUQb4jpEzSFHRcqWUkWwHyxESgDbRNR0rURViEFE4Y5SQ+Y5OET2cZFDsbx9RAfN6kTR/85EiDSpQ2DFEEWd/elD1Ih4RHT6DkW9v+ZEylrBRGh/hERRhvNDS28XRSZEcUVRJ6dFfgApRR9EzUTiWPVFM1U0RWiQpUTlW9lE5tTIRTnnNURdwJBEhZpuQ9WlEUXxGBBEYxyCRLcrBkUhaZdESiSVRIb5MkUmtTNES5anRGc2aESC5OtEAEwlRaKPP0R06o9E5U1FRVB4GUWOeCRFcaNiRchl1ETNFXJFzNEARVw+FEVInQpFJJciRb8Kq0SuDRREGjtSROBDrUNH80JEp+edQ+mJhEQAYyxE56wGRWV2gEQsBAlFtwyCQzOpykOPrTtDynbvRPjrBkVSp9lESbSARO6HhkTRNANFJPEZQ+8PQUUrgBhF0bCCRJ9S50SiT91DuUtqRIe/h0Sf0WBEFsysREB4AUQ7o/tDfxpIRD0q00NYrB1E1WNdRNKuc0P8cjRELw4JQ41/70S9ZkBEE/CCRKVDh0Q2vSlELyi0RKjYCkThsrVCeFf5RJ/s0EMIeIBEamrIQ5oH5UTtmqpE2+ZCQzcTt0QL2zhDODmBRLyjSUXqu4FE3EtFRL3eAkVTz6hEvl5ARFLHt0RBM9RD2HT2RA67SkUtE5dDq6okRbiLMEUjPSNEcC27RECbAUS6ix5FoZEeRB02KkM6w1ZEKRsORbtRAUU1MRhD8zPaQ1VEREXhkBJFbpNHRDuZ/0PrHMpDt82oQ49DN0SI5h1E97V5RKnGOkT/rDpFL8OERADfcUQ/VJxEVQNTRIfpfkSdSaBE7xWiRI0UokS5BKtE6jn2RK73B0WURHJFaZHLRLo9OUTETmBFo+V2ROmI4UQQiBdFClTsQ9yqD0XJeCtEljThRGjX90SMLVlE2qqLRJaaAUSBvk9EnaR6RF879kSDTVhCBMOVQ6z5K0XaVe5DCWTjRGWhjUOAWrJEKbY3RU5aCUSjrp1EisZPRGtnkUQQjrVEK8ONROZ2DESUC59Ek1zXQ8fcAEVW8QtFYQuxRM+SF0RuJKNEm0ZURUE6C0VL6JpEN5TLRKPWN0RiLBRFsswHRY+Ak0SgJsJDCi06RHXqqURhyQ5E5r/dQ0zKPkSE8BlE4tfyRFfyNkR1FwJEPl7oQ8sMhUTGIm5ERDhfRDRVJEQ79+FErVfwQ41r0kQca0REve1FRV5IkETqq8pEkPDFRP6BP0QsgsBELimBRJiEh0RJzrZE5EDvRGCks0MPMO9Dy7u/RAUebkTAU+FCMrD9RFuv6UP7LFxDQNCbRPSBEUSkdaVEZa9kRO4WHkQR0oVEYktTRUOlVEQqWABDJs0jRWqayUTKz4REEh7LQ4SUCUTFg7BEAXG4RBz6PUWUuWNE06yfROileUS6P8xEMRBRRNyem0QxVwFFocwuRMnaDkVWuAREM49CRJzKuENU4vpCGLI4RLyJ3UOIW1xEElcFRGWfjkPZEAFENNZdRHQ+y0MPQ5NEg3VqRWUMMUWFZkpF3poyRM2o4kTw/oBDKrrZQ1NFckODGO1Da4n2REYhd0RX3iZEbqX0QpG5X0QwmptDLzsaRBX54kTFMfBDJ2HsQw7wOET7RtJDK89MQzZ+EUVK3HhDSUdoRA9qH0Q4ZwFFqVunRJ3fLEQQrAVFcr8IRAsXl0NnkoNDwBW9RAl9hERri7NEsb47RD3L1UTm4vNEQd8mRFbBPUQYOzZECNI0RW+wuEOi/UZEOjEFRCoe4kQWjCVE/ECXREQY6EOFDXZEt9lHRFIwhUMHw3xEtFukRJXAJUQHqiZE2SldRGH8tkMgGxdFTn+yQwK2qkSY6nNEYLqOQw2TE0RLTUFE7DnWQygL8UK4s5JDJtC/Q+ECgkR2whpDZRwpRFFGFkTkj9pDmL7PQmSnSENSe41EaigRQ/2f1kORzGhDuuEpRBgDPkTpkQdFQbrKRAvdoESiFDBFEaMIRAERukQmjwpEqyPOQ1MzL0PGsjdF1gxpRIv3tENdHRlD9899RB8aHERJxV1DDNcERIupAEQWcitEaD2pQ8nsOEQ8UwdE9/iFQ7es7kSKJU1Ep8jjQrRs1kQulr9DuVyARCVzEUVvD2VDD3JMQ118sUOsG4BDFqu3RMtxq0MjNjlEv/U8Q8FuvkOUn89DUKbiQ8OoH0SN6stD5YbHQ3H8akT0G71CPCG5Q6gjcEIZ2VVDfTh6RCbJFURpQPBDNf2dRHAcmEOX/BxE18v8Q03DW0MtWJBE/rQtRIPES0Sz7rlE9yLvQzMITURl8E9E/K5SRE+h6kObrglDFsQnRBLhK0QltOFEWc20Q7qThEQKExpEdUebQ5aBhEMrGwVErgCTQ0AcpkRJ5DtErAlwRJ4DX0S1C6FEsdA0RM9L1kN19DJDvKOBRCI+lkRGJDVEdBTyQ1g8+ETZRsZD0nHgQ+PfGkM+yGdDWKXCQzSiO0S16pdEg3dBRCrfy0L8cp9Cz0LAQ6MBgETVeuJD3fpnQwEPYUM3eqJD3Lr1RG50ckPe7qNCjC6vRIYCf0SwMGBErZjvQ129/0Q13U5EBbSARASby0M7aiJDPTMNRPfsp0MCya5El0MaRDJQykLzdglDYd2ZQwqz+EM05YxDfJncQ3l08kPUehdEICMgRK6VLUQCHABEwrsiREVy+UMVlrpDJd/8Qhwf10K32URDUOeYQt5rEUMOIt5CbMVzRAhYpkNtxJpDxXGAQ0wHMEOkSG1EuBPqQkJYGETFRMJCivbORAcDzkOWIbNC6M23RD+mXkQ89AZER0htQ7qwsUOSa5FDWsQBQ20j8EJQx/VCEhJURKvOG0NxSO1CVggLRCEO4UMTMiZDUzYqRKnelkPzkQNDO8VzRCs1SEOackZEqzGmQ5avuUPa2O9CZ2WHQ25j+UTcSkVE11/LQ6d2pEOcrcFCtkaQQg+zvENP7hxEM9R1Q1OldEIJ4JVE+mcSQ2D2L0TYw1RD2FwCRKJr/EOFAQhDt6s2Q+3RyEJo5MFCQ+fdQ5BtN0TIGzBESL4iQ4kPykOWvlZDz20GRAhO4kMV905ECzMNRL0pD0Nf0UhErRQuQ91Fu0I= - - - - - - - - - - - - - - - - - - - - - - - M7RTQ+i0VEOmsVVDzcxWQzOzWENzqlpDYe9cQ5WtYUPhumJDmuFkQwDjb0MvvHRDAAB9QyRkgEMl/oBDFG6BQ8X3gUOT0oJD/G2EQzb2iUNw+opDaVWLQ4ZsjEMAgI1D6PGOQ4lej0PGlZFDA1iTQ8b3k0M3apRDUu2UQwj1lUPhbJZDm4WXQ3D8l0PWB5xDCWCcQ50bnkPiVp5Dj4CfQ6sCoEN78aBD20+iQyKio0NAUqVDiYumQ9T0pkN6WadD4BuoQwCAqEOaGalDNAesQ1aGrENCqK1DSKGvQyRqsUNAm7FDkZ2yQ0DltENwALVDXlq1Q+iFt0PiEblDyNO5Q/6QvUNOCL5D4h+/Q0v/v0M0E8JDyaPDQ3IFxkODksZDfg/HQxJwx0Ns38tDIV/MQxzgzEPSeM1DbKDNQ2bmzUONjM5Dpg/PQ1iKz0MK/89Dwj7QQ7KF0EPOW9FDNBbTQ0pb00NAgdND0t/TQype1UPNTNdD8fbYQ1pT20NmZt9D+O/iQ8R3FkR8/TVEM9NNROPBUUQ= - - - fy+lQrn0rEFmlo1CXTakQY7IPELl+zBDQy5gQ1rpL0I1gOhB/kuJQlfseUP9NjZDpJSXQaSMKkOLKKxDigGFQsxKREPZqA5DGrBnQl2tHUME7j5DPOkvQuwtYEPCQxFCEZVIQxZvBkJyF9BCIw09RDIA0kLQU+VD9dq9QyqsIUJkDrJCREY1Q5tMmkL9J2tDvauRRPbZqENoKIlEn74FRdYjfUKAu49CU7uPQped9EFTp0lCePJNQ7V4hEN9Ta5Df3tORAs8UkIPovxBzkuJQu0W0EL5qA5DWokvQj65F0Seg29DDVCYQlpmk0PD+xpDCbBnQkxUJ0Jjo7pDuo3PQ5EvJUMgS0RDmmXjQnwk/UPwEsFCTYLHQjmnSUKfeGRDwO/jQ6LkvkNbfrhCwbsPQ6a7D0O1R3BDPuGNQpvYsEGJ+utCFlm2Q1g4c0QXh1dEJuSNQ2lcqEOep8lCtoWxQ+7S8EKMWedCd4/0QpZhJEScQxFCMXGLQuJ9uEIENqRB6DfDQmG09kKzXgpDL4/9QWNeCkM= - - - - - - - - - - - - - - - - - - - - - - - ObRQQ621UUNBClRDLuJUQ7LDVUPGt1ZD7rNXQyC1WEOjtVlDytZeQ+rOZEOzTWVDaeJlQ4n2ZkOs0m1DSJhuQzznb0Ou3nBDpHB0Q9vwd0Pm3XhD3r16Q+9ufUPsUIBD6wmBQ36HgUN/6oJDkAaGQ6brh0OID45DqHaOQxOEkENmZpNDPveTQwD4lkPSlpdDUV2ZQ1Bqm0Ph85tDCGKdQ3Xvn0NO76BDUV6iQyP9o0MWV6RDAIekQ6BspUPscaZDDtWmQwB5p0MM06hDKD2qQ5qZq0ODba5DohavQ2ZYr0NM1q9D+n6wQ0l1skNMfrZDp9+3Q0RYuEMbfLlDmpm8Q6pGwUPcjMVDAIDGQ7atx0N7GchDk3fIQ/oNykPQnc1DvRrOQ70G0UP+YNNDvEbUQ+L61UMObtZDNgjXQ7xl10NAn9dDZQ/YQwCA2EMCattDBITdQ4JZ30PwveFD8qXiQ0MW6EPXPu9DrB3wQ6+H9UPNTPdDiAIRRA== - - - MxcQQjbOMkKa2eBETTMmRCgabEMvRXBCNisWQqNhVEPaM7RCZ+mvQqazjEOpOLNCdRpJRWYaakRI+SVDTRPBQ9UpUUPGJodC2Z4rQjkQY0UzFTlDGPJNQha3AEPF+7BDvx/uQjjpL0J2hlZCc1QnQk/cAkPkQOFCsq4cQj3IPEK7r+dBE/wwQ9XWlkRUfjhDDKzYQvrCaER+gkdEp+kvQhvOkEOuuAVCfvbcQky4dkJneuhDN9sdQxVxi0MQGgpEIlCwQqLSH0NJ6S9CWpaNQ3Si/EEisOdCD+tpQljeg0NIUJhD+eARRFZ+OEI/WTZDnkn/QpWJwEOtXUVCGVUnQhtjGUMIgVJE83m9Qcl1mkOF6j5DMGJKQ/LCaEO4DrJCfFdxQzYKI0JXi2VDJmbjQmkrFkJMZL5D9yzrRGLt8UNLP4ZD0LilQxkbX0I2EZxD4tDaQv2eK0NGFzNCBUVwQpc5CENblg1CRcg8Qn6JL0I2dRpCvDotRA== - - - - diff --git a/src/tests/topp/Inspect.mzXML b/src/tests/topp/Inspect.mzXML deleted file mode 100644 index e9f033da27e..00000000000 --- a/src/tests/topp/Inspect.mzXML +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - Instrument Comment - - - - - - Software Comment - - - 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 - - 433.803 - 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 - - 412.168 - Q0+CIkJN8hhDVLsUQhcxWENY7jFCBbiuQ1q5jkMjCllDZujRQmNl/ENn1z5DIwpgQ2iz3EMC3HdDdgvkQ5QF0kOBhYBDEM4JQ4N1/EJFXWRDhYUQQsM340OHMzNByhuGQ4iWrUMC3JxDiVP+Q6W4o0OM2hdDhp2OQ43pM0NVdF9Dj4npQjOE8UOQ7AVCL+lnQ5FzE0LYrCVDklLbQseCTkOS0yFDkM4OQ5QEr0Kv6k5DlHmVQ9m+90OUuDtDAdLjQ5ToIEKZzUNDlX7qQ4y21UOVmYdCxNxzQ5YVPkMQzltDloPjRAOqTkOaIVBCsg51Q5sQmULSPIBDnGL2RB/SokOc5dpDyR6qQ51X10JwRRZDnfH4Q56/40OhHnpChya5Q6OFqULfG1xDpSpyQrQz50On/iRChycMQ67X9kInVLNDsRHSQvBFOkO0uNlDEeCnQ7VUwULc9j9Dtf2GQpQGMkO46RRCj7tqQ7l2mEJSPJ1DvIfgQ5BEzEPBZmZBsNg7Q8Ldd0MlrPNDxAsZQ9Rhq0PFgPhEBhovQ8We2EKQ+m1DyXcHQt8buUPKvORC7h/XQ8tXMULYq/5DzF82QtI8oUPNU6ZDGFBBQ9E4ykNTTtVD01MIQx6/y0Pe5WBCeNpGQ/GKckNiU0hEIj/UQzZZSkQpPUxCXxvzRCpP8EJSPFw= - - - 432.483 - Q1Czz0K4b11DVMzNQiJ6pENVqdZCNAtlQ1aR00K/BdFDWO7vQoyFp0NaLZFC87gAQ2HmvkKkrJJDY7UrQh+IkkNp6uRDBNZTQ27kE0IHBE5Db/4bQoyGDkNxClZDoEhxQ3HYxkPXuN1DcxxAQf60O0Nz6wpDFU43Q3TSFkQTYgNDdeyuQmi9W0N+61dCkOnoQ4BeLkNiJx5DgO7jRBfGL0OC7DxCrXSuQ4NyYUM2PTJDhPUnQoGLJ0OG9ltCl4HoQ4dSjEOWZtFDidIAQoyFaEOKVLpDWEVyQ4xsxENYRWVDjY45QiXCgEOOUqtCUsgdQ5NwQUSKU7BDlIWkQzhvJEOVCr5DAqQmQ5Y5ZkMsW7FDl3SSQnXp00OYHR9DL6a/Q5me4ULU+jpDnGDcQ+PMxUOc9fxCDZ8yQ51si0Pis0xDnmFnQ9uQ5EOe3j1DY0AmQ599ZEURd29Dn7YeQw1vr0Omb5xEGN9OQ6dYtEOCpCtDqAO1Q8JRY0OoXd1EEbZEQ6kQ70MWZwpDqZ2MQ1ypeUOqMnhDl4A+Q7GfIELf9KBDtHb0Q2aLV0O050pCr6bcQ7kIoUQb5B5DugWwQh4XWUO6eSJDg71TQ70gxUIb2CpDvYXeQ8NpmUO+DxZECGe9Q8ITMEMxavBDwluIQ0rBqkPCm9hDIrMMQ8YMnEOCpFdDxn6mQ8XAh0PHB5pDExxsQ8d6HkQFqSxDzFziQytC30PO/HFEJfzPQ89NGUP1NJBDz432QyiQG0PP9C5C6u+sQ9CGLUM6oTpD0mLcQp4WbEPVdvhCUg2CQ9/YEEIZgglD4J1WQlLIA0Ph0exCW5BmRAgdBEJFm5hENUzNQduQHg== - - - 560.388 - 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 - - 432.782 - Q1O0M0KlL39DVLToQaz0uUNVsaZCjZZmQ1bMzUGkNl1DWLMzQjzIjkNaqnNDMPvlQ1zvYUNgLkNDYa2VQi/pWkNiuuFB6IA1Q2ThmkKJS/5Db+MAQ3nsV0N0vC9DNjb9Q30AAEGXlKRDgGQkQyqMpEOA/iVDrCiLQ4FuFEKFAYpDgffFQ0RKzEOC0pNDDqjZQ4Rt/EJnsBpDifY2Qx2tXUOK+nBDPu4EQ4tVaUIv6TxDjGyGQ2At7EONgABCEUPCQ47x6ENIlRFDj16JQgZvFkORlcZC0BdyQ5NYA0Q9DSNDk/fGQtIAMkOUajdD5VPQQ5TtUkO92vVDlfUIQiGsKkOWbOFCsg5kQ5eFm0M1RkRDl/xwQppMm0OcB9ZDayf9Q5xgCUSRq71DnhudQ6jZ9kOeVuJEiShoQ5+Aj0UFvp9DoAKrQn0j1kOg8XtCj7uAQ6JP20KPu1NDo6IiQfSdl0OlUkBCSadTQ6aLiUNN8nhDpvTUQ4R4tUOnWXpDrk19Q6gb4EROe39DqIAAQlI8C0OpGZpB/KIPQ6wHNEKJS85DrIZWQtAW7UOtqEJDDqj5Q6+hSEIviVpDsWokRBe5PkOxm0BDb4OeQ7KdkUKYUA1DtOVAQ5NmWkO1AHBDGvvDQ7VaXkJnsAlDt4XoQidUTEO5EeJDuqNjQ7nTyEPPjbpDvZD+QyUvkUO+CE5DREsgQ78f4kLjZZpDv/9LQ/0kfEPCEzRCwRLwQ8OjyULHgk1DxgVyQkmnOUPGkoNDZHifQ8cPfkPj78BDx3ASQ77kokPL32xCuH5bQ8xfIUMPu8FDzOAcQw+7pkPNeNJDcEe1Q82gbEKN4T5DzeZmQbDYm0POjI1C6/qJQ88PpkO2WRZDz4pYRHM4WEPP/wpEV4cXQ9A+wkON5CZD0IWyQ6hcaUPRW85CyaeeQ9MWNEOxhbZD01tKQvDS7kPTgUBC51mMQ9Pf0kL0j3dD1V4qRCRhlkPXTM1CEUOcQ9j28UKLcTFD21NaQrh94kPfZmZBpDYEQ+Lv+ELDN+hEFnfEQva0YUQ1/XxDCl6zRE3TM0H9jy9EUcHjQwpeYw== - - - 448.45 - Q1C0OUIQFzNDUbWtQjLONkNUCkFE4NmaQ1TiLkQmM01DVcOyQ2waKENWt8ZCcEUvQ1ez7kIWKzZDWLUgQ1Rho0NZtaNCtDPaQ17WykKv6WdDZM7qQ4yzpkNlTbNCszipQ2XiaUVJGnVDZvaJRGoaZkNt0qxDJflIQ26YSEPBE01Db+c8Q1Ep1UNw3q5ChybGQ3RwpEIrntlDd/DbRWMQOUN43eZDORUzQ3q93kJN8hhDfW7vQwC3FkOAUOxDsPvFQ4EJ60LuH79DgYd+Qi/pOEOC6n9CVoZ2Q4YGkEInVHNDh+umQwLcT0OOD4hC4UDkQ452qEIcrrJDkIQTQjzIPUOTZmZB56+7Q5P3PkMw/BNDlvgARJbW1UOXltJDOH5UQ5ldUULYrAxDm2pQRGjC+kOb8+FER4J+Q51iCEIv6adDn+91Q5DOG0Og705CBbiuQ6JeUULc9n5Do/0jQna4TEOkVxZD6HpnQ6SHAEMd2zdDpWygQ4txFUOmcexEChoQQ6bVDkKwUCJDp3kAQx/SokOo0wxCL+lJQ6o9KEONllpDq5maQfyidEOubYNC57AiQ68WokJp6w9Dr1hmQ4PeWEOv1kxDmFBIQ7B++kQR4PlDsnVJQjh+VkO2fkxDNlk/Q7ffp0L/SZ5DuFhEQ8CJlUO5fBtCRV2tQ7yZmkInVRlDwUaqQxljG0PFjNxEUoEIQ8aAAEG9efNDx622Q5p1yUPIGXtDPuqFQ8h3k0NKYjBDyg36Q2jC8kPNndBCsg64Q84avUNxV3xD0Qa9QiMKNkPTYP5DZYtXQ9RGvELjZiZD1friQhYraUPWbg5DvmRMQ9cINkTrLPdD12W8Q/HtYkPXn0BDhj9LQ9gPZUOluNBD2IAAQl8bGUPbagJDnBE2Q92EBELa0OJD31mCQyue/UPhvfBCMxdGQ+Kl8kJwRQVD6BZDQwg5l0PvPtdCDZZbQ/AdrEI8yEVD9YevQi+JfkP3TM1CGnU2RBECiEQtOrw= - - - - 0 - diff --git a/src/tests/topp/InspectAdapter.out b/src/tests/topp/InspectAdapter.out deleted file mode 100644 index 154dc7b83c0..00000000000 --- a/src/tests/topp/InspectAdapter.out +++ /dev/null @@ -1,2 +0,0 @@ -#SpectrumFile Scan# Annotation Protein Charge MQScore CutScore IntenseBY BYPresent NTT p-value DeltaScore DeltaScoreOther RecordNumber DBFilePos SpecFilePos -Inspect.mzXML 13 E.NQGD.E Q9CQV8|1433B_MOUSE 1 -12.839 1.273 0.150 0.167 0.000 0.97500 0.000 0.000 3 826 50881 diff --git a/src/tests/topp/InspectAdapter_1_output.modification_list.txt b/src/tests/topp/InspectAdapter_1_output.modification_list.txt deleted file mode 100644 index 83acee08ef6..00000000000 --- a/src/tests/topp/InspectAdapter_1_output.modification_list.txt +++ /dev/null @@ -1,3 +0,0 @@ -name composition amino_acids -Phosphorylation HO3P STYDHCR - diff --git a/src/tests/topp/InspectAdapter_1_parameters.ini b/src/tests/topp/InspectAdapter_1_parameters.ini deleted file mode 100644 index f9a11fe305c..00000000000 --- a/src/tests/topp/InspectAdapter_1_parameters.ini +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/topp/InspectAdapter_2_output.inspect_in b/src/tests/topp/InspectAdapter_2_output.inspect_in deleted file mode 100644 index 8c1a3ecabc5..00000000000 --- a/src/tests/topp/InspectAdapter_2_output.inspect_in +++ /dev/null @@ -1,14 +0,0 @@ -spectra,dummy.mzXML -db,dummy.trie -protease,Trypsin -mod,10.3,KRLNH,fix,PTM_0 -mod,16,C,opt,PTM_1 -mod,-16,CTERM,opt,PTM_2 -mod,-16,NTERM,opt,PTM_3 -mods,5 -maxptmsize,250 -PM_tolerance,1 -IonTolerance,0.5 -multicharge,1 -instrument,QTOF -TagCount,3 diff --git a/src/tests/topp/InspectAdapter_2_parameters.ini b/src/tests/topp/InspectAdapter_2_parameters.ini deleted file mode 100644 index 1df29a28a3e..00000000000 --- a/src/tests/topp/InspectAdapter_2_parameters.ini +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/topp/InspectAdapter_4_output.idXML b/src/tests/topp/InspectAdapter_4_output.idXML deleted file mode 100644 index d17dcd011df..00000000000 --- a/src/tests/topp/InspectAdapter_4_output.idXML +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/tests/topp/Inspect_FASTAFile_test.fasta b/src/tests/topp/Inspect_FASTAFile_test.fasta deleted file mode 100644 index b86cb6a6e3f..00000000000 --- a/src/tests/topp/Inspect_FASTAFile_test.fasta +++ /dev/null @@ -1,13 +0,0 @@ ->P68509|1433F_BOVIN -GDREQLLQRARLAEQAERYDDMASAMKAVTELNEPLSNEDRNLLSVAYKNVVGARRSSWR -VISSIEQKTMADGNEKKLEKVKAYREKIEKELETVCNDVLALLDKFLIKNCNDFQYESKV -FYLKMKGDYYRYLAEVASGEKKNSVVEASEAAYKEAFEISKEHMQPTHPIRLGLALNFSV -FYYEIQNAPEQACLLAKQAFDDAIAELDTLNEDSYKDSTLIMQLLRDNLTLWTSDQQDEE -AGEGN - ->Q9CQV8|1433B_MOUSE -TMDKSELVQKAKLAEQAERYDDMAAAMKAVTEQGHELSNEERNLLSVAYKNVVGARRSSW -RVISSIEQKTERNEKKQQMGKEYREKIEAELQDICNDVLELLDKYLILNATQAESKVFYL -KMKGDYFRYLSEVASGENKQTTVSNSQQAYQEAFEISKKEMQPTHPIRLGLALNFSVFYY -EILNSPEKACSLAKTAFDEAIAELDTLNEESYKDSTLIMQLLRDNLTLWTSENQGDEGDA -GEGEN diff --git a/src/tests/topp/Inspect_FASTAFile_test.index b/src/tests/topp/Inspect_FASTAFile_test.index deleted file mode 100644 index e7bf108fed8..00000000000 Binary files a/src/tests/topp/Inspect_FASTAFile_test.index and /dev/null differ diff --git a/src/tests/topp/Inspect_FASTAFile_test.trie b/src/tests/topp/Inspect_FASTAFile_test.trie deleted file mode 100644 index c3ddf0e02e9..00000000000 --- a/src/tests/topp/Inspect_FASTAFile_test.trie +++ /dev/null @@ -1 +0,0 @@ -MKVLILACLVALALARELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPPFLQPEVMGVSKVKEAMAPKHKEMPFPKYPVEPFTESQSLTLTDVENLHLPLPLLQSWMHQPHQPLPPTVMFPPQSVLSLSQSKVLPVPQKAVPYPQRDMPIQAFLLYQEPVLGPVRGPFPIIV*SAPPSLLVLYFGKKELRAMKVLILACLVALALARELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPP*GDREQLLQRARLAEQAERYDDMASAMKAVTELNEPLSNEDRNLLSVAYKNVVGARRSSWRVISSIEQKTMADGNEKKLEKVKAYREKIEKELETVCNDVLALLDKFLIKNCNDFQYESKVFYLKMKGDYYRYLAEVASGEKKNSVVEASEAAYKEAFEISKEHMQPTHPIRLGLALNFSVFYYEIQNAPEQACLLAKQAFDDAIAELDTLNEDSYKDSTLIMQLLRDNLTLWTSDQQDEEAGEGN*TMDKSELVQKAKLAEQAERYDDMAAAMKAVTEQGHELSNEERNLLSVAYKNVVGARRSSWRVISSIEQKTERNEKKQQMGKEYREKIEAELQDICNDVLELLDKYLILNATQAESKVFYLKMKGDYFRYLSEVASGENKQTTVSNSQQAYQEAFEISKKEMQPTHPIRLGLALNFSVFYYEILNSPEKACSLAKTAFDEAIAELDTLNEESYKDSTLIMQLLRDNLTLWTSENQGDEGDAGEGEN diff --git a/src/tests/topp/Inspect_FASTAFile_test2.index b/src/tests/topp/Inspect_FASTAFile_test2.index deleted file mode 100644 index 77498238b0d..00000000000 Binary files a/src/tests/topp/Inspect_FASTAFile_test2.index and /dev/null differ diff --git a/src/tests/topp/Inspect_FASTAFile_test2.trie b/src/tests/topp/Inspect_FASTAFile_test2.trie deleted file mode 100644 index fec45f4a1fd..00000000000 --- a/src/tests/topp/Inspect_FASTAFile_test2.trie +++ /dev/null @@ -1 +0,0 @@ -MKVLILACLVALALARELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPPFLQPEVMGVSKVKEAMAPKHKEMPFPKYPVEPFTESQSLTLTDVENLHLPLPLLQSWMHQPHQPLPPTVMFPPQSVLSLSQSKVLPVPQKAVPYPQRDMPIQAFLLYQEPVLGPVRGPFPIIV*SAPPSLLVLYFGKKELRAMKVLILACLVALALARELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPP diff --git a/src/tests/topp/Inspect_FASTAFile_test4.index b/src/tests/topp/Inspect_FASTAFile_test4.index deleted file mode 100644 index e7bf108fed8..00000000000 Binary files a/src/tests/topp/Inspect_FASTAFile_test4.index and /dev/null differ diff --git a/src/tests/topp/Inspect_FASTAFile_test4.trie b/src/tests/topp/Inspect_FASTAFile_test4.trie deleted file mode 100644 index c3ddf0e02e9..00000000000 --- a/src/tests/topp/Inspect_FASTAFile_test4.trie +++ /dev/null @@ -1 +0,0 @@ -MKVLILACLVALALARELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPPFLQPEVMGVSKVKEAMAPKHKEMPFPKYPVEPFTESQSLTLTDVENLHLPLPLLQSWMHQPHQPLPPTVMFPPQSVLSLSQSKVLPVPQKAVPYPQRDMPIQAFLLYQEPVLGPVRGPFPIIV*SAPPSLLVLYFGKKELRAMKVLILACLVALALARELEELNVPGEIVESLSSSEESITRINKKIEKFQSEEQQQTEDELQDKIHPFAQTQSLVYPFPGPIPNSLPQNIPPLTQTPVVVPP*GDREQLLQRARLAEQAERYDDMASAMKAVTELNEPLSNEDRNLLSVAYKNVVGARRSSWRVISSIEQKTMADGNEKKLEKVKAYREKIEKELETVCNDVLALLDKFLIKNCNDFQYESKVFYLKMKGDYYRYLAEVASGEKKNSVVEASEAAYKEAFEISKEHMQPTHPIRLGLALNFSVFYYEIQNAPEQACLLAKQAFDDAIAELDTLNEDSYKDSTLIMQLLRDNLTLWTSDQQDEEAGEGN*TMDKSELVQKAKLAEQAERYDDMAAAMKAVTEQGHELSNEERNLLSVAYKNVVGARRSSWRVISSIEQKTERNEKKQQMGKEYREKIEAELQDICNDVLELLDKYLILNATQAESKVFYLKMKGDYFRYLSEVASGENKQTTVSNSQQAYQEAFEISKKEMQPTHPIRLGLALNFSVFYYEILNSPEKACSLAKTAFDEAIAELDTLNEESYKDSTLIMQLLRDNLTLWTSENQGDEGDAGEGEN diff --git a/src/tests/topp/Inspect_FASTAFile_test5.index b/src/tests/topp/Inspect_FASTAFile_test5.index deleted file mode 100644 index 997da8d5a1b..00000000000 Binary files a/src/tests/topp/Inspect_FASTAFile_test5.index and /dev/null differ diff --git a/src/tests/topp/Inspect_FASTAFile_test5.trie b/src/tests/topp/Inspect_FASTAFile_test5.trie deleted file mode 100644 index fb75faecedd..00000000000 --- a/src/tests/topp/Inspect_FASTAFile_test5.trie +++ /dev/null @@ -1 +0,0 @@ -*GDREQLLQRARLAEQAERYDDMASAMKAVTELNEPLSNEDRNLLSVAYKNVVGARRSSWRVISSIEQKTMADGNEKKLEKVKAYREKIEKELETVCNDVLALLDKFLIKNCNDFQYESKVFYLKMKGDYYRYLAEVASGEKKNSVVEASEAAYKEAFEISKEHMQPTHPIRLGLALNFSVFYYEIQNAPEQACLLAKQAFDDAIAELDTLNEDSYKDSTLIMQLLRDNLTLWTSDQQDEEAGEGN*TMDKSELVQKAKLAEQAERYDDMAAAMKAVTEQGHELSNEERNLLSVAYKNVVGARRSSWRVISSIEQKTERNEKKQQMGKEYREKIEAELQDICNDVLELLDKYLILNATQAESKVFYLKMKGDYFRYLSEVASGENKQTTVSNSQQAYQEAFEISKKEMQPTHPIRLGLALNFSVFYYEILNSPEKACSLAKTAFDEAIAELDTLNEESYKDSTLIMQLLRDNLTLWTSENQGDEGDAGEGEN diff --git a/src/tests/topp/Inspect_PTMs.xml b/src/tests/topp/Inspect_PTMs.xml deleted file mode 100644 index 912fa917ed2..00000000000 --- a/src/tests/topp/Inspect_PTMs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - Phosphorylation - HO3P - STYDHCR - - diff --git a/src/tests/topp/QCCalculator_2_output.mzQC b/src/tests/topp/QCCalculator_2_output.mzQC index db88e8b2a2a..17d6350749a 100644 --- a/src/tests/topp/QCCalculator_2_output.mzQC +++ b/src/tests/topp/QCCalculator_2_output.mzQC @@ -1,112 +1,113 @@ { "mzQC": { - "creationDate": "2021-03-29T10:09:41", + "creationDate": "2021-04-14T12:11:57", "version": "1.0.0", "contactName": "name", "contactAddress": "address", "description": "description", - "runQualities": { - "metadata": { - "label": "label", - "inputFiles": [ - { - "location": "/home/axel/Development/OpenMS/src/tests/topp/QCCalculator_input.mzML", - "name": "QCCalculator_input.mzML", - "fileFormat": { - "accession": "MS:10000584", - "name": "mzML format" - } - }, - "fileProperties", - [ - { - "accession": "MS:1000747", - "name": "completion time", - "value": "2007-06-27T15:23:45" - }, + "runQualities": [ + { + "metadata": { + "label": "label", + "inputFiles": [ { - "accession": "MS:1000569", - "name": "SHA-1", - "value": "24aeada3affec9df36568c0054e4197ac3515642" - }, + "location": "/home/axel/Development/OpenMS/src/tests/topp/QCCalculator_input.mzML", + "name": "QCCalculator_input.mzML", + "fileFormat": { + "accession": "MS:10000584", + "name": "mzML format" + }, + "fileProperties": [ + { + "accession": "MS:1000747", + "name": "completion time", + "value": "2007-06-27T15:23:45" + }, + { + "accession": "MS:1000569", + "name": "SHA-1", + "value": "24aeada3affec9df36568c0054e4197ac3515642" + }, + { + "accession": "MS:1000031", + "name": "instrument model", + "value": "LCQ Deca" + } + ] + } + ], + "analysisSoftware": [ { - "accession": "MS:1000031", - "name": "instrument model", - "value": "LCQ Deca" + "accession": "MS:1009001", + "name": "QCCalculator", + "version": "2.6.0", + "uri": "https://www.openms.de" } ] - ], - "analysisSoftware": [ - { - "accession": "MS:1009001", - "name": "QCCalculator", - "version": "2.6.0", - "uri": "https://www.openms.de" - } - ] - }, - "qualityMetrics": [ - { - "accession": "QC:4000059", - "name": "Number of MS1 spectra", - "value": 3 }, - { - "accession": "QC:4000060", - "name": "Number of MS2 spectra", - "value": 1 - }, - { - "accession": "QC:4000135", - "name": "Number of chromatograms", - "value": 2 - }, - { - "accession": "QC:4000053", - "name": "RT duration", - "value": 360 - }, - { - "accession": "QC:4000138", - "name": "MZ acquisition range", - "value": [ - 0, - 678 - ] - }, - { - "accession": "QC:4000067", - "name": "Total ion current chromatogram", - "value": { - "Relative intensity": [ + "qualityMetrics": [ + { + "accession": "QC:4000059", + "name": "Number of MS1 spectra", + "value": 3 + }, + { + "accession": "QC:4000060", + "name": "Number of MS2 spectra", + "value": 1 + }, + { + "accession": "QC:4000135", + "name": "Number of chromatograms", + "value": 2 + }, + { + "accession": "QC:4000053", + "name": "RT duration", + "value": 360 + }, + { + "accession": "QC:4000138", + "name": "MZ acquisition range", + "value": [ 0, - 120, - 120 - ], - "Retention time": [ - -1.0, - 42.04999923706055, - 353.42999267578125 + 678 ] + }, + { + "accession": "QC:4000067", + "name": "Total ion current chromatogram", + "value": { + "Relative intensity": [ + 0, + 120, + 120 + ], + "Retention time": [ + -1.0, + 42.04999923706055, + 353.42999267578125 + ] + } + }, + { + "accession": "QC:4000077", + "name": "Area under TIC", + "value": 240 + }, + { + "accession": "QC:4000172", + "name": "MS1 signal jump (10x) count", + "value": 1 + }, + { + "accession": "QC:4000173", + "name": "MS1 signal fall (10x) count", + "value": 0 } - }, - { - "accession": "QC:4000077", - "name": "Area under TIC", - "value": 240 - }, - { - "accession": "QC:4000172", - "name": "MS1 signal jump (10x) count", - "value": 1 - }, - { - "accession": "QC:4000173", - "name": "MS1 signal fall (10x) count", - "value": 0 - } - ] - }, + ] + } + ], "controlledVocabularies": [ { "name": "Proteomics Standards Initiative Quality Control Ontology", diff --git a/src/topp/CompNovo.cpp b/src/topp/CompNovo.cpp index 42b87991927..0d208bd50e1 100644 --- a/src/topp/CompNovo.cpp +++ b/src/topp/CompNovo.cpp @@ -199,8 +199,8 @@ class TOPPCompNovo : search_parameters.digestion_enzyme = *(ProteaseDB::getInstance()->getEnzyme("no cleavage")); } search_parameters.mass_type = ProteinIdentification::MONOISOTOPIC; - search_parameters.fixed_modifications = algorithm_param.getValue("fixed_modifications"); - search_parameters.variable_modifications = algorithm_param.getValue("variable_modifications"); + search_parameters.fixed_modifications = ListUtils::toStringList(algorithm_param.getValue("fixed_modifications")); + search_parameters.variable_modifications = ListUtils::toStringList(algorithm_param.getValue("variable_modifications")); search_parameters.missed_cleavages = (UInt)algorithm_param.getValue("missed_cleavages"); search_parameters.fragment_mass_tolerance = (double)algorithm_param.getValue("fragment_mass_tolerance"); diff --git a/src/topp/CompNovoCID.cpp b/src/topp/CompNovoCID.cpp index 1bd0604a95a..8687f77a5ed 100644 --- a/src/topp/CompNovoCID.cpp +++ b/src/topp/CompNovoCID.cpp @@ -199,8 +199,8 @@ class TOPPCompNovoCID : search_parameters.digestion_enzyme = *(ProteaseDB::getInstance()->getEnzyme("no cleavage")); } search_parameters.mass_type = ProteinIdentification::MONOISOTOPIC; - search_parameters.fixed_modifications = algorithm_param.getValue("fixed_modifications"); - search_parameters.variable_modifications = algorithm_param.getValue("variable_modifications"); + search_parameters.fixed_modifications = ListUtils::toStringList(algorithm_param.getValue("fixed_modifications")); + search_parameters.variable_modifications = ListUtils::toStringList(algorithm_param.getValue("variable_modifications")); search_parameters.missed_cleavages = (UInt)algorithm_param.getValue("missed_cleavages"); search_parameters.fragment_mass_tolerance = (double)algorithm_param.getValue("fragment_mass_tolerance"); diff --git a/src/topp/FeatureFinderMetabo.cpp b/src/topp/FeatureFinderMetabo.cpp index d7680b2778f..30fc93bd0d3 100644 --- a/src/topp/FeatureFinderMetabo.cpp +++ b/src/topp/FeatureFinderMetabo.cpp @@ -148,7 +148,7 @@ class TOPPFeatureFinderMetabo : Param p_epd; p_epd.setValue("enabled", "true", "Enable splitting of isobaric mass traces by chromatographic peak detection. Disable for direct injection."); - p_epd.setValidStrings("enabled", ListUtils::create("true,false")); + p_epd.setValidStrings("enabled", {"true","false"}); p_epd.insert("", ElutionPeakDetection().getDefaults()); p_epd.remove("chrom_peak_snr"); p_epd.remove("chrom_fwhm"); diff --git a/src/topp/FileConverter.cpp b/src/topp/FileConverter.cpp index 01e340896b6..4c0e9c0b1b4 100644 --- a/src/topp/FileConverter.cpp +++ b/src/topp/FileConverter.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -123,6 +124,7 @@ using namespace std; @ref OpenMS::SpecArrayFile "peplist" @ref OpenMS::KroenikFile "kroenik" @ref OpenMS::EDTAFile "edta" + @ref OpenMS::SqMassFile "sqmass" @note See @ref TOPP_IDFileConverter for similar functionality for protein/peptide identification file formats. @@ -336,7 +338,7 @@ class TOPPFileConverter : String method("none,ensure,reassign"); setValidStrings_("UID_postprocessing", ListUtils::create(method)); - vector output_formats = {"mzML", "mzXML", "cachedMzML", "mgf", "featureXML", "consensusXML", "edta", "mzData", "dta2d", "csv"}; + vector output_formats = {"mzML", "mzXML", "cachedMzML", "mgf", "featureXML", "consensusXML", "edta", "mzData", "dta2d", "csv", "sqmass"}; registerOutputFile_("out", "", "", "Output file"); setValidFormats_("out", output_formats); registerStringOption_("out_type", "", "", "Output file type -- default: determined from file extension or content\nNote: that not all conversion paths work or make sense.", false, true); @@ -411,13 +413,7 @@ class TOPPFileConverter : // output file names and types String out = getStringOption_("out"); - FileTypes::Type out_type = FileTypes::nameToType(getStringOption_("out_type")); - - if (out_type == FileTypes::UNKNOWN) - { - out_type = fh.getTypeByFileName(out); - } - + FileTypes::Type out_type = FileHandler::getConsistentOutputfileType(out, getStringOption_("out_type")); if (out_type == FileTypes::UNKNOWN) { writeLog_("Error: Could not determine output file type!"); @@ -880,6 +876,11 @@ class TOPPFileConverter : IBSpectraFile ibfile; ibfile.store(out, cm); } + else if (out_type == FileTypes::SQMASS) + { + SqMassFile sqm; + sqm.store(out, exp); + } else { writeLog_("Unknown output file type given. Aborting!"); diff --git a/src/topp/FileInfo.cpp b/src/topp/FileInfo.cpp index 8c94b3695a0..872906f38c9 100644 --- a/src/topp/FileInfo.cpp +++ b/src/topp/FileInfo.cpp @@ -444,15 +444,16 @@ class TOPPFileInfo : public TOPPBase { vector entries; FASTAFile file; - - Map aacids; // required for default construction of non-existing keys - size_t number_of_aacids = 0; + file.setLogType(log_type_); SysInfo::MemUsage mu; // loading input file.load(in, entries); std::cout << "\n\n" << mu.delta("loading FASTA") << std::endl; + Map aacids;// required for default construction of non-existing keys + size_t number_of_aacids = 0; + Size dup_header(0); Size dup_seq(0); diff --git a/src/topp/FileMerger.cpp b/src/topp/FileMerger.cpp index e9c0f7a301a..f6d1793d940 100644 --- a/src/topp/FileMerger.cpp +++ b/src/topp/FileMerger.cpp @@ -436,7 +436,7 @@ class TOPPFileMerger : } else if (rt_filename) { - static const boost::regex re("rt(\\d+(\\.\\d+)?)"); + static const boost::regex re(R"(rt(\d+(\.\d+)?))"); boost::smatch match; bool found = boost::regex_search(filename, match, re); if (found) diff --git a/src/topp/GenericWrapper.cpp b/src/topp/GenericWrapper.cpp index bc106d3d990..a7a07abcef3 100644 --- a/src/topp/GenericWrapper.cpp +++ b/src/topp/GenericWrapper.cpp @@ -180,9 +180,9 @@ class TOPPGenericWrapper : String paramToString_(const Param::ParamEntry & p) { - if (p.value.valueType() == DataValue::STRING_LIST) // quote each element + if (p.value.valueType() == ParamValue::STRING_LIST) // quote each element { - StringList val = p.value; + StringList val = ListUtils::toStringList(p.value); if (p.tags.count("input file") || p.tags.count("output file")) { for (Size i = 0; i < val.size(); ++i) @@ -195,11 +195,11 @@ class TOPPGenericWrapper : if (p.tags.count("input file") || p.tags.count("output file")) { // ensure that file names are formated according to system spec - return QDir::toNativeSeparators(p.value.toQString()); + return QDir::toNativeSeparators(String(p.value.toString()).toQString()); } else { - return p.value; + return p.value.toString(); } } @@ -274,7 +274,7 @@ class TOPPGenericWrapper : // %DIR% replace { - QRegExp rx("%DIR\\[(.*)\\]"); + QRegExp rx(R"(%DIR\[(.*)\])"); rx.setMinimal(true); int pos = 0; QString t_tmp = fragment.toQString(); @@ -293,7 +293,7 @@ class TOPPGenericWrapper : // %BASENAME% replace { - QRegExp rx("%BASENAME\\[(.*)\\]"); + QRegExp rx(R"(%BASENAME\[(.*)\])"); rx.setMinimal(true); int pos = 0, count = 0; QString t_tmp = fragment.toQString(); @@ -371,7 +371,7 @@ class TOPPGenericWrapper : { if ((it->tags).count("required") > 0) { - String in = it->value.toString().trim(); // will give '[]' for empty lists (hack, but DataValue class does not offer a convenient query) + String in = String(it->value.toString()).trim(); // will give '[]' for empty lists (hack, but DataValue class does not offer a convenient query) if (in.empty() || in == "[]") // any required parameter should have a value { OPENMS_LOG_ERROR << "The INI-parameter 'ETool:" << it->name << "' is required, but was not given! Aborting ..." << std::endl; @@ -382,11 +382,11 @@ class TOPPGenericWrapper : StringList ifs; switch (it->value.valueType()) { - case DataValue::STRING_VALUE: - ifs.push_back(it->value); + case ParamValue::STRING_VALUE: + ifs.push_back(it->value.toChar()); break; - case DataValue::STRING_LIST: - ifs = it->value; + case ParamValue::STRING_LIST: + ifs = ListUtils::toStringList(it->value); break; default: OPENMS_LOG_ERROR << "The INI-parameter 'ETool:" << it->name << "' is tagged as input file and thus must be a string! Aborting ..."; @@ -447,7 +447,7 @@ class TOPPGenericWrapper : createFragment_(tmp_location, p); // check if target already exists: - String target_file = (String)p.getValue(target); + String target_file = p.getValue(target).toString(); if (File::exists(tmp_location)) { if (!File::remove(tmp_location)) @@ -517,7 +517,7 @@ class TOPPGenericWrapper : // check if target already exists: String target = fm.target; if (!p.exists(target)) throw Exception::InvalidValue(__FILE__, __LINE__, OPENMS_PRETTY_FUNCTION, "Cannot find target parameter '" + target + "' being mapped from external tools output!", target); - String target_file = (String)p.getValue(target); + String target_file = p.getValue(target).toString(); if (target_file.trim().empty()) // if target was not given, we skip the copying step (usually for optional parameters) { diff --git a/src/topp/IDFileConverter.cpp b/src/topp/IDFileConverter.cpp index d2cc0f4158a..e1f9be5b5c5 100644 --- a/src/topp/IDFileConverter.cpp +++ b/src/topp/IDFileConverter.cpp @@ -220,7 +220,7 @@ class TOPPIDFileConverter : vector all_enzymes; ProteaseDB::getInstance()->getAllNames(all_enzymes); p.setValue("enzyme", "Trypsin", "Enzym used to digest the fasta proteins"); - p.setValidStrings("enzyme", all_enzymes); + p.setValidStrings("enzyme", ListUtils::create(all_enzymes)); p.setValue("missed_cleavages", 0, "Number of allowed missed cleavages while digesting the fasta proteins"); p.setValue("min_charge", 1, "Minimum charge"); p.setValue("max_charge", 1, "Maximum charge"); @@ -282,6 +282,14 @@ class TOPPIDFileConverter : const String in = getStringOption_("in"); const String mz_file = getStringOption_("mz_file"); + const String out = getStringOption_("out"); + FileTypes::Type out_type = FileHandler::getConsistentOutputfileType(out, getStringOption_("out_type")); + if (out_type == FileTypes::UNKNOWN) + { + writeLog_("Error: Could not determine output file type!"); + return PARSE_ERROR; + } + ProgressLogger logger; logger.setLogType(ProgressLogger::CMD); logger.startProgress(0, 1, "Loading..."); @@ -590,8 +598,6 @@ class TOPPIDFileConverter : else if (in_type == FileTypes::FASTA) { // handle out type - const String out = getStringOption_("out"); - FileTypes::Type out_type = FileTypes::nameToType(getStringOption_("out_type")); if (out_type != FileTypes::MZML) { writeLog_("Error: Illegal output file type given. Fasta can only be converted to an MzML. Aborting!"); @@ -604,7 +610,7 @@ class TOPPIDFileConverter : // extract parameters and remove non tsg params Param p = getParam_().copy("fasta_to_mzml:", true); - String enzyme = p.getValue("enzyme"); + String enzyme = p.getValue("enzyme").toString(); Int mc = p.getValue("missed_cleavages"); Int min_charge = p.getValue("min_charge"); Int max_charge = p.getValue("max_charge"); @@ -686,18 +692,6 @@ class TOPPIDFileConverter : //------------------------------------------------------------- // writing output //------------------------------------------------------------- - const String out = getStringOption_("out"); - FileTypes::Type out_type = FileTypes::nameToType(getStringOption_("out_type")); - if (out_type == FileTypes::UNKNOWN) - { - out_type = fh.getTypeByFileName(out); - } - if (out_type == FileTypes::UNKNOWN) - { - writeLog_("Error: Could not determine output file type!"); - return PARSE_ERROR; - } - logger.startProgress(0, 1, "Storing..."); if (out_type == FileTypes::PEPXML) diff --git a/src/topp/IDFilter.cpp b/src/topp/IDFilter.cpp index 19d5ed1ce4f..87b396c2b8d 100644 --- a/src/topp/IDFilter.cpp +++ b/src/topp/IDFilter.cpp @@ -181,7 +181,7 @@ class TOPPIDFilter : registerFlag_("blacklist:ignore_modifications", "Compare blacklisted peptides by sequence only.", true); registerStringList_("blacklist:modifications", "", vector(), "Remove all peptides with sequences that contain (any of) the selected modification(s)", false, true); setValidStrings_("blacklist:modifications", all_mods); - + registerStringOption_("blacklist:RegEx", "", "", "Remove all peptides with (unmodified) sequences matched by the RegEx e.g. [BJXZ] removes ambiguous peptides.", false, true); registerTOPPSubsection_("in_silico_digestion", "This filter option removes peptide hits which are not in the list of in silico peptides generated by the rules specified below"); registerInputFile_("in_silico_digestion:fasta", "", "", "fasta protein sequence database.", false); setValidFormats_("in_silico_digestion:fasta", ListUtils::create("fasta")); @@ -453,6 +453,11 @@ class TOPPIDFilter : IDFilter::removePeptidesWithMatchingModifications(peptides, bad_mods); } + String blacklist_regex = getStringOption_("blacklist:RegEx"); + if (!blacklist_regex.empty()) + { + IDFilter::removePeptidesWithMatchingRegEx(peptides, blacklist_regex); + } if (getFlag_("best:strict")) { diff --git a/src/topp/IDMapper.cpp b/src/topp/IDMapper.cpp index 4cf951e16f3..caf37685aa9 100644 --- a/src/topp/IDMapper.cpp +++ b/src/topp/IDMapper.cpp @@ -147,9 +147,9 @@ class TOPPIDMapper : registerDoubleOption_("mz_tolerance", "", p.getValue("mz_tolerance"), "m/z tolerance (in ppm or Da) for the matching of peptide identifications and (consensus) features.\nTolerance is understood as 'plus or minus x', so the matching range increases by twice the given value.", false); setMinFloat_("mz_tolerance", 0.0); registerStringOption_("mz_measure", "", p.getEntry("mz_measure").valid_strings[0], "Unit of 'mz_tolerance'.", false); - setValidStrings_("mz_measure", p.getEntry("mz_measure").valid_strings); + setValidStrings_("mz_measure", ListUtils::toStringList(p.getEntry("mz_measure").valid_strings)); registerStringOption_("mz_reference", "", p.getEntry("mz_reference").valid_strings[1], "Source of m/z values for peptide identifications. If 'precursor', the precursor-m/z from the idXML is used. If 'peptide',\nmasses are computed from the sequences of peptide hits; in this case, an identification matches if any of its hits matches.\n('peptide' should be used together with 'feature:use_centroid_mz' to avoid false-positive matches.)", false); - setValidStrings_("mz_reference", p.getEntry("mz_reference").valid_strings); + setValidStrings_("mz_reference", ListUtils::toStringList(p.getEntry("mz_reference").valid_strings)); registerFlag_("ignore_charge", "For feature/consensus maps: Assign an ID independently of whether its charge state matches that of the (consensus) feature.", true); addEmptyLine_(); diff --git a/src/topp/IDPosteriorErrorProbability.cpp b/src/topp/IDPosteriorErrorProbability.cpp index ca71715df63..ff7f9f1c317 100644 --- a/src/topp/IDPosteriorErrorProbability.cpp +++ b/src/topp/IDPosteriorErrorProbability.cpp @@ -159,7 +159,7 @@ class TOPPIDPosteriorErrorProbability : double fdr_for_targets_smaller = getDoubleOption_("fdr_for_targets_smaller"); bool ignore_bad_data = getFlag_("ignore_bad_data"); bool prob_correct = getFlag_("prob_correct"); - String outlier_handling = fit_algorithm.getValue("outlier_handling"); + String outlier_handling = fit_algorithm.getValue("outlier_handling").toString(); //------------------------------------------------------------- // reading input @@ -204,7 +204,7 @@ class TOPPIDPosteriorErrorProbability : if (!ignore_bad_data) { return INPUT_FILE_EMPTY; } } - String out_plot = fit_algorithm.getValue("out_plot").toString().trim(); + String out_plot = String(fit_algorithm.getValue("out_plot").toString()).trim(); for (auto & score : all_scores) { diff --git a/src/topp/InspectAdapter.cpp b/src/topp/InspectAdapter.cpp deleted file mode 100644 index 12e99809f9f..00000000000 --- a/src/topp/InspectAdapter.cpp +++ /dev/null @@ -1,921 +0,0 @@ -// -------------------------------------------------------------------------- -// OpenMS -- Open-Source Mass Spectrometry -// -------------------------------------------------------------------------- -// Copyright The OpenMS Team -- Eberhard Karls University Tuebingen, -// ETH Zurich, and Freie Universitaet Berlin 2002-2020. -// -// This software is released under a three-clause BSD license: -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// * Neither the name of any author or any participating institution -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// For a full list of authors, refer to the file AUTHORS. -// -------------------------------------------------------------------------- -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING -// INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// -------------------------------------------------------------------------- -// $Maintainer: Timo Sachsenberg $ -// $Authors: $ -// -------------------------------------------------------------------------- - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -using namespace OpenMS; -using namespace std; - -//------------------------------------------------------------- -//Doxygen docu -//------------------------------------------------------------- - -/** - @page TOPP_InspectAdapter InspectAdapter - - @brief Identifies peptides in MS/MS spectra via Inspect. - -
-
NameTypeDefaultRestrictionsDescription
- - - - - - - - - -
pot. predecessor tools \f$ \longrightarrow \f$ InspectAdapter \f$ \longrightarrow \f$ pot. successor tools
any signal-/preprocessing tool @n (in mzML format) @ref TOPP_IDFilter or @n any protein/peptide processing tool
- - - @experimental This tool has not been tested thoroughly and might behave not as expected! - - This wrapper application serves for getting peptide peptide_identifications - for MS/MS spectra. The wrapper can be executed in three different - modes: -
    -
  1. - The whole process of ProteinIdentification via Inspect is executed. - Inputfile is an mz file containing the MS/MS spectra - (Supported spectrum file formats are .mzXML, .mzData) - for which the identifications are to be found and one ore more - databases in either trie, FASTA or Swissprot format containing - the possible proteins. - The given databases are converted and merged into one trie database. - This is done because Inspect does the conversion anyway - (though with a bug) and may actually not use more than two - databases (one of them in trie format). Additionally you thus can - reuse the database without having Inspect done the conversion - every time. - The drawback is, of course, that you need the same amount of space - for the trie database as well, which can, in case of large and/or many - databases, be a problem. - The results are written as a idXML output file. This mode is selected - by default. -
  2. - -
  3. - Only the first part of the ProteinIdentification process is performed. - This means that an Inspect input file is generated and the given databases are - converted and merged into one trie database. This file can be used - directly with Inspect whereas the created database and the spectrum file(s) - have to remain at the given positions. - Calling an Inspect process should look like the following: - - @code ./inspect -i inputfilename -o outputfilename @endcode - - Consult your Inspect reference manual for further details. - - This mode is selected by the -inspect_in option in the command line. -
  4. - -
  5. - Only the second part of the ProteinIdentification process is performed. - This means that the output of an Inspect run is analyzed and the result - written to an idXML file. - - This mode is selected by the -inspect_out option in the command line. -
  6. -
- - @note Currently mzIdentML (mzid) is not directly supported as an input/output format of this tool. Convert mzid files to/from idXML using @ref TOPP_IDFileConverter if necessary. - - The command line parameters of this tool are: - @verbinclude TOPP_InspectAdapter.cli - INI file documentation of this tool: - @htmlinclude TOPP_InspectAdapter.html - - @todo rewrite the Adapter! It uses old formats and coding style, e.g. mzData input allowed, no input restrictions, manual (unneccessary file checking of input files) etc... - + the interface is not convenient, etc ... - -*/ - -// We do not want this class to show up in the docu -> cond -/// @cond TOPPCLASSES - -class TOPPInspectAdapter : - public TOPPBase -{ -public: - TOPPInspectAdapter() : - TOPPBase("InspectAdapter", "Annotates MS/MS spectra using Inspect.") - { - } - -protected: - void registerOptionsAndFlags_() override - { - registerInputFile_("in", "", "", "input file in mzXML or mzData format.\n" - "Note: In mode 'inspect_out' an Inspect results (txt) file is read."); - setValidFormats_("in", ListUtils::create("mzXML,mzData,txt")); - registerOutputFile_("out", "", "", "output file in idXML format.\n" - "Note: In mode 'inspect_in' an Inspect input file is written as txt."); - setValidFormats_("out", ListUtils::create("idXML,txt")); - registerFlag_("inspect_in", "if this flag is set the InspectAdapter will read in mzXML,\n" - "write an Inspect input file and generate a trie database"); - registerFlag_("inspect_out", "if this flag is set the InspectAdapter will read in a Inspect results file\n" - "and write idXML"); - registerStringOption_("inspect_directory", "", "", "the directory in which Inspect is located", false); - registerStringOption_("temp_data_directory", "", "", "a directory in which some temporary files can be stored", false); - registerStringOption_("dbs", "", "", "name(s) of database(s) to search in (FASTA and SwissProt supported)", false); - registerStringOption_("trie_dbs", "", "", "name(s) of databases(s) to search in (trie-format)", false); - registerStringOption_("new_db", "", "", "name of the merged trie database", false); - registerStringOption_("instrument", "", "", "the instrument that was used to measure the spectra\n" - "(If set to QTOF, uses a QTOF-derived fragmentation model,\n" - "and does not attempt to correct the parent mass.)", false); - setValidStrings_("instrument", ListUtils::create("ESI-ION-TRAP,QTOF,FT-Hybrid")); - registerDoubleOption_("precursor_mass_tolerance", "", 2.0, "the precursor mass tolerance", false); - registerDoubleOption_("peak_mass_tolerance", "", 1.0, "the peak mass tolerance", false); - registerFlag_("list_modifications", "show a list of the available modifications"); - registerStringOption_("modifications", "", "", "the colon-separated modifications; may be\n" - ",, e.g.: Deamidation,opt or\n" - ",,,, e.g.: H2C2O,KCS,opt,Acetyl or\n" - ",,,, e.g.: 42.0367,KCS,opt,Acetyl or\n" - "Valid values for type are \"fix\" and \"opt\" (default)\n" - "If you want terminal PTMs, write \"cterm\" or \"nterm\" instead of residues", false); - registerFlag_("use_monoisotopic_mod_mass", "use monoisotopic masses for the modifications"); - registerStringOption_("modifications_xml_file", "", "", "name of an XML file with the modifications", false); - registerStringOption_("cleavage", "", "Trypsin", "the enzyme used for digestion", false); - registerOutputFile_("inspect_output", "", "", "name for the output file of Inspect (may only be used in a full run)", false); - setValidFormats_("inspect_output", ListUtils::create("txt")); - registerInputFile_("inspect_input", "", "", "name for the input file of Inspect (may only be used in a full run)", false); - setValidFormats_("inspect_input", ListUtils::create("txt")); - registerFlag_("multicharge", "attempt to guess the precursor charge and mass,\n" - "and consider multiple charge states if feasible"); - registerIntOption_("max_modifications_pp", "", -1, "number of PTMs permitted in a single peptide.", false); - registerIntOption_("tag_count", "", -1, "number of tags to generate", false); - registerFlag_("no_tmp_dbs", "no temporary databases are used"); - registerDoubleOption_("p_value", "", 1.0, "annotations with inferior p-value are ignored", false); - - registerTOPPSubsection_("blind", "Options for blind search"); - registerFlag_("blind:blind", "perform a blind search (allowing arbitrary modification masses),\n" - "is preceeded by a normal search to gain a smaller database.\n" - "(in full mode only)"); - registerFlag_("blind:blind_only", "like blind but no prior search is performed to reduce the database size"); - registerDoubleOption_("blind:p_value_blind", "", 1.0, "used for generating the minimized database", false); - registerStringOption_("blind:snd_db", "", "", "name of the minimized trie database generated when using blind mode.", false); - registerDoubleOption_("blind:max_ptm_size", "", 250.0, "maximum modification size (in Da) to consider", false); - - addEmptyLine_(); - registerStringOption_("contact_name", "", "unknown", "Name of the contact", false); - registerStringOption_("contact_institution", "", "unknown", "Name of the contact institution", false); - registerStringOption_("contact_info", "", "unknown", "Some information about the contact", false); - } - - ExitCodes main_(Int, const char**) override - { - //------------------------------------------------------------- - // (1) variables - //------------------------------------------------------------- - - InspectInfile inspect_infile; - InspectOutfile inspect_outfile; - - vector - trie_database_filenames, - sequence_database_filenames, - index_filenames; - - String - string_buffer, - trie_database_filename, - index_filename, - snd_trie_database_filename, - snd_index_filename, - inspect_logfile, - logfile, - inspect_directory, - temp_data_directory, - snd_trie_database, - snd_trie_database_directory, - output_filename, - inspect_input_filename, - inspect_output_filename, - modifications_filename, - isotope_filename; - - bool - inspect_in(false), - inspect_out(false), - blind_only(false), - blind(false), - monoisotopic(false); - - double p_value_threshold(1.0); - - char separator = '/'; - - ContactPerson contact_person; - - ExitCodes exit_code = EXECUTION_OK; - - // filename and tag: file has to: 1 - exist 2 - be readable 4 - writable 8 - be deleted afterwards - map files; - Size const - exist(1), - readable(2), - writable(4), - delete_afterwards(8); - - //------------------------------------------------------------- - // (2) parsing and checking parameters - //------------------------------------------------------------- - - modifications_filename = getStringOption_("modifications_xml_file"); - - if (getFlag_("list_modifications")) - { - if (modifications_filename.empty()) - { - writeLog_("No modifications XML file given. Aborting!"); - return INPUT_FILE_NOT_FOUND; - } - if (!File::readable(modifications_filename)) - { - writeLog_("Modifications XML file is not readable. Aborting!"); - return INPUT_FILE_NOT_READABLE; - } - map > PTM_informations; - try - { - PTMXMLFile().load(modifications_filename, PTM_informations); - } - catch (Exception::ParseError& pe) - { - writeLog_(pe.getMessage()); - return PARSE_ERROR; - } - - // output the information - stringstream PTM_info; - String::size_type max_name_length(4), max_composition_length(11), max_amino_acids_length(11); - for (map >::const_iterator mod_it = PTM_informations.begin(); mod_it != PTM_informations.end(); ++mod_it) - { - max_name_length = max(max_name_length, mod_it->first.length()); - max_composition_length = max(max_composition_length, mod_it->second.first.length()); - max_amino_acids_length = max(max_amino_acids_length, mod_it->second.second.length()); - } - PTM_info << "name" << String(max_name_length - 4, ' ') << "\t" << "composition" << String(max_composition_length - 11, ' ') << "\t" << "amino_acids" << String(max_amino_acids_length - 11, ' ') << endl; - for (map >::const_iterator mod_it = PTM_informations.begin(); mod_it != PTM_informations.end(); ++mod_it) - { - PTM_info << mod_it->first << String(max_name_length - mod_it->first.length(), ' ') << "\t" << mod_it->second.first << String(max_composition_length - mod_it->second.first.length(), ' ') << "\t" << mod_it->second.second << String(max_amino_acids_length - mod_it->second.second.length(), ' ') << endl; - } - std::cout << PTM_info.str() << std::endl; - - return EXECUTION_OK; - } - - logfile = getStringOption_("log"); - if (logfile.empty()) - { - logfile = "temp.inspect.log"; - files[logfile] = (writable | delete_afterwards); - } - else files[logfile] = writable; - - inspect_in = getFlag_("inspect_in"); - inspect_out = getFlag_("inspect_out"); - - if (inspect_in && inspect_out) - { - writeLog_("Both Inspect flags set. Only one of the two flags [-inspect_in|-inspect_out] can be set. Aborting!"); - return ILLEGAL_PARAMETERS; - } - - if (inspect_in) writeDebug_("Inspect flag: mascot_in (reads in MzXML/MzData, writes Inspect generic format)", 1); - else if (inspect_out) writeDebug_("Inspect flag: mascot_in (reads in Inspect result file, writes idXML file)", 1); - else writeDebug_("No Inspect flag set: reads in MzXML/MzData, writes idXML file", 1); - - // a 'normal' inspect run corresponds to both inspect_in and inspect_out set - if (!inspect_in && !inspect_out) inspect_in = inspect_out = true; - - if (inspect_out && inspect_in) - { - temp_data_directory = getStringOption_("temp_data_directory"); - if (temp_data_directory.empty()) - { - writeLog_("No directory for temporary files specified. Aborting!"); - printUsage_(); - return ILLEGAL_PARAMETERS; - } - temp_data_directory = File::absolutePath(temp_data_directory); - temp_data_directory.ensureLastChar(separator); - } - - string_buffer = getStringOption_("in"); - if (string_buffer.empty()) - { - writeLog_("No input file specified. Aborting!"); - printUsage_(); - return ILLEGAL_PARAMETERS; - } - else - { - string_buffer = File::absolutePath(string_buffer); - if (inspect_in) - { - PeakMap experiment; - String type; - try - { - inspect_outfile.getExperiment(experiment, type, string_buffer); // may throw an exception if the filetype could not be determined - } - catch (Exception::ParseError& pe) - { - writeLog_(pe.getMessage()); - return PARSE_ERROR; - } - if (type != "mzXML") - { - string_buffer.append(".mzXML"); - MzXMLFile().store(string_buffer, experiment); - files[string_buffer] = (writable | delete_afterwards); - } - inspect_infile.setSpectra(string_buffer); - - if (inspect_out) - { - inspect_output_filename = getStringOption_("inspect_output"); - if (inspect_output_filename.empty()) - { - inspect_output_filename = temp_data_directory + "tmp.direct.inspect.output"; - files[inspect_output_filename] = (writable | delete_afterwards); - } - else - { - inspect_output_filename = File::absolutePath(inspect_output_filename); - files[inspect_output_filename] = writable; - } - } - } - else - { - inspect_output_filename = string_buffer; - inspect_output_filename = File::absolutePath(inspect_output_filename); - files[inspect_output_filename] = readable; - } - } - - string_buffer = getStringOption_("out"); - if (string_buffer.empty()) - { - writeLog_("No output file specified. Aborting!"); - return ILLEGAL_PARAMETERS; - } - else - { - string_buffer = File::absolutePath(string_buffer); - if (inspect_out) output_filename = string_buffer; - else inspect_input_filename = string_buffer; - files[string_buffer] = writable; - } - - if (inspect_in && inspect_out) - { - inspect_input_filename = getStringOption_("inspect_input"); - if (inspect_input_filename.empty()) - { - inspect_input_filename = temp_data_directory + "tmp.inspect.input"; - files[inspect_input_filename] = (writable | delete_afterwards); - } - else - { - inspect_input_filename = File::absolutePath(inspect_input_filename); - files[inspect_input_filename] = writable; - } - } - - inspect_directory = getStringOption_("inspect_directory"); - if (inspect_in && inspect_directory.empty() && inspect_out) - { - writeLog_("No inspect directory file specified. Aborting!"); - return ILLEGAL_PARAMETERS; - } - inspect_directory = File::absolutePath(inspect_directory); - inspect_directory.ensureLastChar(separator); - - blind_only = getFlag_("blind:blind_only"); - - contact_person.setName(getStringOption_("contact_name")); - contact_person.setInstitution(getStringOption_("contact_institution")); - contact_person.setContactInfo(getStringOption_("contact_info")); - - if (inspect_in) - { - string_buffer = getStringOption_("trie_dbs"); - if (!string_buffer.empty()) - { - // get the single databases - string_buffer.split(',', trie_database_filenames); - if (trie_database_filenames.empty()) trie_database_filenames.push_back(string_buffer); - - // the database files have to be readable, (by the way changing the names using the absolute path) - for (vector::iterator trie_database_filenames_it = trie_database_filenames.begin(); trie_database_filenames_it != trie_database_filenames.end(); ++trie_database_filenames_it) - { - *trie_database_filenames_it = File::absolutePath(*trie_database_filenames_it); - files[*trie_database_filenames_it] = readable; - - // get the according index file - if (trie_database_filenames_it->hasSuffix(".trie")) string_buffer = trie_database_filenames_it->substr(0, trie_database_filenames_it->length() - 4) + "index"; - else string_buffer = *trie_database_filenames_it + "index"; - index_filenames.push_back(string_buffer); - files[string_buffer] = readable; - } - } - - string_buffer = getStringOption_("dbs"); - if (!string_buffer.empty()) - { - // get the single sequence files - string_buffer.split(',', sequence_database_filenames); - if (sequence_database_filenames.empty()) sequence_database_filenames.push_back(string_buffer); - // the sequence files have to be readable, (by the way changing the names using the absolute path) - for (vector::iterator sequence_database_filenames_it = sequence_database_filenames.begin(); sequence_database_filenames_it != sequence_database_filenames.end(); ++sequence_database_filenames_it) - { - *sequence_database_filenames_it = File::absolutePath(*sequence_database_filenames_it); - files[*sequence_database_filenames_it] = readable; - } - } - - // at least one of the parameters db or sequence_file has to be set - if (trie_database_filenames.empty() && sequence_database_filenames.empty()) - { - writeLog_("No database specified. Aborting!"); - return ILLEGAL_PARAMETERS; - } - - bool no_tmp_dbs = getFlag_("no_tmp_dbs"); - - // blind - running inspect in blind mode after running a normal mode to minimize the database - blind = getFlag_("blind:blind"); - if (blind && inspect_in && !inspect_out) - { - blind = false; - blind_only = true; - } - - trie_database_filename = getStringOption_("new_db"); - if (trie_database_filename.empty() && (!sequence_database_filenames.empty() || trie_database_filenames.size() != 1)) - { - if (!inspect_out) - { - writeLog_("No name for new trie database given. Aborting!"); - return ILLEGAL_PARAMETERS; - } - else - { - if (no_tmp_dbs) - { - writeLog_("no_tmp_dbs flag set but no name for database given. Aborting!"); - return ILLEGAL_PARAMETERS; - } - else - { - trie_database_filename = temp_data_directory + "tmp.inspect.db.trie"; - files[trie_database_filename] = (writable | delete_afterwards); - inspect_infile.setDb(trie_database_filename); - index_filename = temp_data_directory + "tmp.inspect.db.index"; - files[index_filename] = (writable | delete_afterwards); - } - } - } - else - { - // if only one trie database is given, this one is used - if (trie_database_filename.empty()) trie_database_filename = trie_database_filenames.front(); - - trie_database_filename = File::absolutePath(trie_database_filename); - if (trie_database_filename.hasSuffix(".trie")) - { - inspect_infile.setDb(trie_database_filename); - index_filename = trie_database_filename.substr(0, trie_database_filename.length() - 4) + "index"; - } - else - { - index_filename = trie_database_filename + ".index"; - trie_database_filename = trie_database_filename + ".trie"; - inspect_infile.setDb(trie_database_filename); - } - files[trie_database_filename] = writable; - files[index_filename] = writable; - } - - if (blind && blind_only) - { - writeLog_("Both blind flags set. Only one of the two flags [-blind|-blind_only] can be set. Aborting!"); - return ILLEGAL_PARAMETERS; - } - - snd_trie_database = getStringOption_("blind:snd_db"); - if (no_tmp_dbs && blind && snd_trie_database.empty()) - { - writeLog_("No_tmp_dbs and blind flag set but no name for minimized database given. Aborting!"); - return ILLEGAL_PARAMETERS; - } - else if (blind && snd_trie_database.empty()) - { - snd_trie_database_filename = temp_data_directory + "tmp.inspect.db.snd.trie"; - snd_index_filename = temp_data_directory + "tmp.inspect.db.snd.index"; - files[snd_trie_database_filename] = (writable | delete_afterwards); - files[snd_index_filename] = (writable | delete_afterwards); - } - else if (blind) - { - snd_trie_database = File::absolutePath(snd_trie_database); - if (snd_trie_database.hasSuffix(".trie")) - { - snd_trie_database_filename = snd_trie_database; - snd_index_filename = snd_trie_database.substr(0, snd_trie_database.size() - 4) + "index"; - files[snd_trie_database_filename] = writable; - files[snd_index_filename] = writable; - } - else - { - snd_trie_database_filename = snd_trie_database + ".trie"; - snd_index_filename = snd_trie_database + ".index"; - files[snd_trie_database_filename] = writable; - files[snd_index_filename] = writable; - } - } - - // get the known modifications - monoisotopic = getFlag_("use_monoisotopic_mod_mass"); - if (!blind_only) - { - // modifications - string_buffer = getStringOption_("modifications"); - try - { - inspect_infile.handlePTMs(string_buffer, modifications_filename, monoisotopic); - } - catch (Exception::FileNotFound& /*fnf_e*/) - { - writeLog_("No modifications XML file given. Aborting!"); - return INPUT_FILE_NOT_FOUND; - } - catch (Exception::FileNotReadable& /*fnr_e*/) - { - writeLog_("Modifications XML file is not readable. Aborting!"); - return INPUT_FILE_NOT_READABLE; - } - catch (Exception::ParseError& p_e) - { - writeLog_(String(p_e.getMessage()) + ". Aborting!"); - return PARSE_ERROR; - } - } - - inspect_infile.setEnzyme(getStringOption_("cleavage")); - inspect_infile.setInstrument(getStringOption_("instrument")); - - inspect_infile.setModificationsPerPeptide(getIntOption_("max_modifications_pp")); - if (inspect_infile.getModificationsPerPeptide() < 1 && !inspect_infile.getModifications().empty()) - { - writeLog_("Modifications specified, but max_modifications_pp not set. Setting it to 1."); - inspect_infile.setModificationsPerPeptide(1); - } - - inspect_infile.setPrecursorMassTolerance(getDoubleOption_("precursor_mass_tolerance")); - if ((inspect_infile.getPrecursorMassTolerance() < 0 && inspect_infile.getPrecursorMassTolerance() != -1)) - { - writeLog_("Illegal precursor mass tolerance (<0) given. Aborting!"); - return ILLEGAL_PARAMETERS; - } - - inspect_infile.setPeakMassTolerance(getDoubleOption_("peak_mass_tolerance")); - if ((inspect_infile.getPeakMassTolerance() < 0 && inspect_infile.getPeakMassTolerance() != -1)) - { - writeLog_("Illegal peak mass tolerance (<0) given. Aborting!"); - return ILLEGAL_PARAMETERS; - } - - if (getFlag_("multicharge")) inspect_infile.setMulticharge(1); - - inspect_infile.setTagCount(getIntOption_("tag_count")); - if ((inspect_infile.getTagCount() < 0 && inspect_infile.getTagCount() != -1)) - { - writeLog_("Illegal number of tags (tag_count <0) given. Aborting!"); - return ILLEGAL_PARAMETERS; - } - - inspect_infile.setMaxPTMsize(getDoubleOption_("blind:max_ptm_size")); - if ((inspect_infile.getMaxPTMsize() < 10 || inspect_infile.getMaxPTMsize() > 2000) && inspect_infile.getMaxPTMsize() != -1) - { - writeLog_("Illegal maximum modification size (not in [10,2000]). Aborting!"); - return ILLEGAL_PARAMETERS; - } - } - - if (inspect_out) - { - p_value_threshold = getDoubleOption_("p_value"); - if ((p_value_threshold < 0) || (p_value_threshold > 1)) - { - writeLog_("Illegal p-value. Aborting!"); - return ILLEGAL_PARAMETERS; - } - - inspect_logfile = temp_data_directory + "tmp.inspect.log"; - files[inspect_logfile] = (writable | delete_afterwards); - } - - if (blind && inspect_in) - { - double cutoff_p_value = getDoubleOption_("blind:p_value_blind"); - if ((cutoff_p_value < 0) || (cutoff_p_value > 1)) - { - writeLog_("Illegal p-value for blind search. Aborting!"); - return ILLEGAL_PARAMETERS; - } - } - - //------------------------------------------------------------- - // (3) running program according to parameters - //------------------------------------------------------------- - // checking accessability of files - - Size file_tag(0); - - for (map::const_iterator files_it = files.begin(); files_it != files.end(); ++files_it) - { - string_buffer = files_it->first; - file_tag = files_it->second; - - if ((file_tag & exist || file_tag & readable) && !File::exists(string_buffer)) - { - exit_code = INPUT_FILE_NOT_FOUND; - writeLog_(String("File ") + string_buffer + " does not exist. Aborting!"); - break; - } - - if ((file_tag & readable) && !File::readable(string_buffer)) - { - exit_code = INPUT_FILE_NOT_READABLE; - writeLog_(String("File ") + string_buffer + " is not readable. Aborting!"); - break; - } - - bool existed = File::exists(string_buffer); - if ((file_tag & writable) && !File::writable(string_buffer)) - { - exit_code = CANNOT_WRITE_OUTPUT_FILE; - writeLog_(String("Cannot write file ") + string_buffer + ". Aborting!"); - break; - } - else if (!existed) remove(string_buffer.c_str()); - existed = false; - } - - vector wanted_records; - - // creating the input file and converting and merging the databases - if (exit_code == EXECUTION_OK && inspect_in) - { - if (!sequence_database_filenames.empty() || trie_database_filenames.size() != 1) // don't do it, if only one trie database is given - { - // merging the trie databases (all but the first databases are appended) - vector::const_iterator index_filenames_itt = index_filenames.begin(); - for (vector::const_iterator trie_database_filenames_it = trie_database_filenames.begin(); trie_database_filenames_it != trie_database_filenames.end(); ++trie_database_filenames_it, ++index_filenames_itt) - { - inspect_outfile.compressTrieDB(*trie_database_filenames_it, *index_filenames_itt, wanted_records, trie_database_filename, index_filename, (trie_database_filenames_it != trie_database_filenames.begin())); - } - - // converting and merging the other databases (all but the first database are appended) - for (vector::const_iterator sequence_database_filenames_it = sequence_database_filenames.begin(); sequence_database_filenames_it != sequence_database_filenames.end(); ++sequence_database_filenames_it) - { - inspect_outfile.generateTrieDB(*sequence_database_filenames_it, trie_database_filename, index_filename, ((sequence_database_filenames_it != sequence_database_filenames.begin()) || (!sequence_database_filenames.empty()))); - } - } - - if (blind_only) inspect_infile.setBlind(true); - - inspect_infile.store(inspect_input_filename); - } - - // running inspect and generating a second database from the results and running inspect in blind mode on this new database - if (exit_code == EXECUTION_OK && blind && inspect_in && inspect_out) - { - writeLog_("Searching and generating minimised database for blind mode ..."); - writeDebug_("The Inspect process created the following output:", 1); - String call; - call.append(" -r "); - call.append(inspect_directory); - call.append(" -i "); - call.append(inspect_input_filename); - call.append(" -o "); - call.append(inspect_output_filename); - // writing the inspect output to a temporary file - call.append(" -e "); - call.append(inspect_logfile); - - Int status = QProcess::execute((inspect_directory + "inspect").toQString(), QStringList(call.toQString().split(" ", QString::SkipEmptyParts))); // does automatic escaping etc... - if (status != 0) - { - TextFile tf(inspect_logfile); - string_buffer.clear(); - string_buffer.concatenate(tf.begin(), tf.end()); - writeLog_("Inspect problem: " + string_buffer + " Aborting!"); - - exit_code = EXTERNAL_PROGRAM_ERROR; - } - - wanted_records = inspect_outfile.getWantedRecords(inspect_output_filename, p_value_threshold); - - if (wanted_records.empty()) - { - IdXMLFile idXML_file; - idXML_file.store(output_filename, vector(), vector()); - inspect_out = false; - writeLog_("No proteins matching criteria for generating minimized database for blind search. Aborting!"); - exit_code = UNKNOWN_ERROR; - } - else - { - inspect_outfile.compressTrieDB(trie_database_filename, index_filename, wanted_records, snd_trie_database_filename, snd_index_filename, false); - - // setting the database name to the new database - inspect_infile.setDb(snd_trie_database_filename); - inspect_infile.setBlind(true); - inspect_infile.store(inspect_input_filename); - } - } - - // writing the output of inspect Into an idXML file - if (exit_code == EXECUTION_OK && inspect_in && inspect_out) - { - String call; - call.append(" -r "); - call.append(inspect_directory); - call.append(" -i "); - call.append(inspect_input_filename); - call.append(" -o "); - call.append(inspect_output_filename); - // writing the inspect output to a temporary file - call.append(" -e "); - call.append(inspect_logfile); - - writeLog_("Searching ..."); - writeDebug_("The Inspect process created the following output:", 1); - - Int status = QProcess::execute((inspect_directory + "inspect").toQString(), QStringList(call.toQString().split(" ", QString::SkipEmptyParts))); // does automatic escaping etc... - if (status != 0) - { - TextFile tf(inspect_logfile); - string_buffer.clear(); - string_buffer.concatenate(tf.begin(), tf.end()); - writeLog_("Inspect problem: " + string_buffer + ". Aborting!"); - exit_code = EXTERNAL_PROGRAM_ERROR; - } - } - - if (exit_code == EXECUTION_OK && inspect_out) - { - vector peptide_identifications; - ProteinIdentification protein_identification; - IdXMLFile idXML_file; - - if (inspect_in) // the version can only be retrieved by running inspect without parameters - { - // first get the InsPecT version - QProcess builder; - builder.start((inspect_directory + "inspect").toQString(), QStringList()); // does automatic escaping etc... - - if (!builder.waitForFinished(-1)) - { - writeLog_("Inspect problem: " + String(QString(builder.readAll())) + ". Aborting!"); - exit_code = EXTERNAL_PROGRAM_ERROR; - } - else - { - QString output = builder.readAll(); - // set the search engine and its version and the score type - if (!inspect_outfile.getSearchEngineAndVersion(output, protein_identification)) OPENMS_LOG_WARN << "Could not read version of InsPecT from:\n" << String(output) << "\n\n"; - } - } - else protein_identification.setSearchEngine("InsPecT"); - - if (exit_code == EXECUTION_OK) - { - if (!File::empty(inspect_output_filename)) - { - // set the parameters - ProteinIdentification::SearchParameters sp; - if (monoisotopic) - { - sp.mass_type = ProteinIdentification::MONOISOTOPIC; - } - else - { - sp.mass_type = ProteinIdentification::AVERAGE; - } - - if (ProteaseDB::getInstance()->hasEnzyme(inspect_infile.getEnzyme())) - { - sp.digestion_enzyme = *(ProteaseDB::getInstance()->getEnzyme(inspect_infile.getEnzyme())); - } - sp.fragment_mass_tolerance = inspect_infile.getPeakMassTolerance(); - sp.precursor_mass_tolerance = inspect_infile.getPrecursorMassTolerance(); - protein_identification.setSearchParameters(sp); - - try - { - inspect_outfile.load(inspect_output_filename, peptide_identifications, protein_identification, p_value_threshold, inspect_infile.getDb()); - } - catch (Exception::ParseError& pe) - { - writeLog_(pe.getMessage()); - exit_code = INPUT_FILE_CORRUPT; - } - if (exit_code == EXECUTION_OK) - { - vector protein_identifications(1, protein_identification); - - // write all (!) parameters as metavalues to the search parameters - if (!protein_identifications.empty()) - { - DefaultParamHandler::writeParametersToMetaValues(this->getParam_(), protein_identifications[0].getSearchParameters(), this->getToolPrefix()); - } - - idXML_file.store(output_filename, protein_identifications, peptide_identifications); - } - } - else - { - idXML_file.store(output_filename, vector(), vector()); - writeLog_("No proteins identified!"); - } - } - } - - // if an external program error occurred, the logfile must not be deleted - if (exit_code == EXTERNAL_PROGRAM_ERROR) - { - writeLog_("PepNovo problem. Aborting! (Details can be seen in the logfile: \"" + logfile + "\")"); - files[logfile] = readable; - } - // deleting all temporary files - for (map::const_iterator files_it = files.begin(); files_it != files.end(); ++files_it) - { - if (files_it->second & delete_afterwards) remove(files_it->first.c_str()); - } - - return exit_code; - } - -}; - -Int main(Int argc, const char** argv) -{ - TOPPInspectAdapter tool; - - return tool.main(argc, argv); -} - -///@endcond diff --git a/src/topp/MapAlignerIdentification.cpp b/src/topp/MapAlignerIdentification.cpp index b5fb73c0fd1..b2725f8adba 100644 --- a/src/topp/MapAlignerIdentification.cpp +++ b/src/topp/MapAlignerIdentification.cpp @@ -160,7 +160,7 @@ class TOPPMapAlignerIdentification : { // find model parameters: Param model_params = getParam_().copy("model:", true); - String model_type = model_params.getValue("type"); + String model_type = model_params.getValue("type").toString(); try { diff --git a/src/topp/MapAlignerSpectrum.cpp b/src/topp/MapAlignerSpectrum.cpp index 7fafea46251..7c6fb691bfe 100644 --- a/src/topp/MapAlignerSpectrum.cpp +++ b/src/topp/MapAlignerSpectrum.cpp @@ -135,7 +135,7 @@ class TOPPMapAlignerSpectrum : StringList outs = getStringList_("out"); StringList trafos = getStringList_("trafo_out"); Param model_params = getParam_().copy("model:", true); - String model_type = model_params.getValue("type"); + String model_type = model_params.getValue("type").toString(); model_params = model_params.copy(model_type + ":", true); std::vector transformations; diff --git a/src/topp/MapRTTransformer.cpp b/src/topp/MapRTTransformer.cpp index 0b9b43a54cd..bc927295244 100644 --- a/src/topp/MapRTTransformer.cpp +++ b/src/topp/MapRTTransformer.cpp @@ -151,7 +151,7 @@ class TOPPMapRTTransformer : String trafo_in = getStringOption_("trafo_in"); String trafo_out = getStringOption_("trafo_out"); Param model_params = getParam_().copy("model:", true); - String model_type = model_params.getValue("type"); + String model_type = model_params.getValue("type").toString(); model_params = model_params.copy(model_type + ":", true); ProgressLogger progresslogger; diff --git a/src/topp/MassTraceExtractor.cpp b/src/topp/MassTraceExtractor.cpp index 3889e3afedd..ad1953703af 100644 --- a/src/topp/MassTraceExtractor.cpp +++ b/src/topp/MassTraceExtractor.cpp @@ -138,7 +138,7 @@ class TOPPMassTraceExtractor : p_epd.remove("chrom_fwhm"); p_epd.setValue("enabled", "true", "Enables/disables the chromatographic peak detection of mass traces"); - p_epd.setValidStrings("enabled", ListUtils::create("true,false")); + p_epd.setValidStrings("enabled", {"true","false"}); combined.insert("epd:", p_epd); return combined; diff --git a/src/topp/OpenSwathRTNormalizer.cpp b/src/topp/OpenSwathRTNormalizer.cpp index 4a47bda9671..d20506c8dee 100644 --- a/src/topp/OpenSwathRTNormalizer.cpp +++ b/src/topp/OpenSwathRTNormalizer.cpp @@ -149,10 +149,10 @@ class TOPPOpenSwathRTNormalizer : public TOPPBase { Param p; p.setValue("outlierMethod", "iter_residual", "Which outlier detection method to use (valid: 'iter_residual', 'iter_jackknife', 'ransac', 'none'). Iterative methods remove one outlier at a time. Jackknife approach optimizes for maximum r-squared improvement while 'iter_residual' removes the datapoint with the largest residual error (removal by residual is computationally cheaper, use this with lots of peptides)."); - p.setValidStrings("outlierMethod", ListUtils::create("iter_residual,iter_jackknife,ransac,none")); + p.setValidStrings("outlierMethod", {"iter_residual","iter_jackknife","ransac","none"}); p.setValue("useIterativeChauvenet", "false", "Whether to use Chauvenet's criterion when using iterative methods. This should be used if the algorithm removes too many datapoints but it may lead to true outliers being retained."); - p.setValidStrings("useIterativeChauvenet", ListUtils::create("true,false")); + p.setValidStrings("useIterativeChauvenet", {"true","false"}); p.setValue("RANSACMaxIterations", 1000, "Maximum iterations for the RANSAC outlier detection algorithm."); p.setValue("RANSACMaxPercentRTThreshold", 3, "Maximum threshold in RT dimension for the RANSAC outlier detection algorithm (in percent of the total gradient). Default is set to 3% which is around +/- 4 minutes on a 120 gradient."); @@ -189,7 +189,7 @@ class TOPPOpenSwathRTNormalizer : public TOPPBase Param pepEstimationParams = getParam_().copy("peptideEstimation:", true); Param RTNormParams = getParam_().copy("RTNormalization:", true); - String outlier_method = RTNormParams.getValue("outlierMethod"); + String outlier_method = RTNormParams.getValue("outlierMethod").toString(); // 1. Estimate the retention time range of the whole experiment std::pair RTRange = OpenSwathHelper::estimateRTRange(targeted_exp); diff --git a/src/topp/PTPredict.cpp b/src/topp/PTPredict.cpp index 36ec523f829..3b4d5c97d52 100644 --- a/src/topp/PTPredict.cpp +++ b/src/topp/PTPredict.cpp @@ -159,7 +159,7 @@ class TOPPPTPredict : paramFile.load(in_params_name, additional_parameters); if (additional_parameters.getValue("kernel_type") != DataValue::EMPTY) { - svm.setParameter(SVMWrapper::KERNEL_TYPE, ((String) additional_parameters.getValue("kernel_type")).toInt()); + svm.setParameter(SVMWrapper::KERNEL_TYPE, String( additional_parameters.getValue("kernel_type").toString()).toInt()); } if (additional_parameters.getValue("border_length") == DataValue::EMPTY @@ -169,7 +169,7 @@ class TOPPPTPredict : cout << "No border length saved in additional parameters file. Aborting!" << endl; return ILLEGAL_PARAMETERS; } - border_length = ((String)additional_parameters.getValue("border_length")).toInt(); + border_length = String(additional_parameters.getValue("border_length").toString()).toInt(); if (additional_parameters.getValue("k_mer_length") == DataValue::EMPTY && svm.getIntParameter(SVMWrapper::KERNEL_TYPE) == SVMWrapper::OLIGO) { @@ -177,7 +177,7 @@ class TOPPPTPredict : cout << "No k-mer length saved in additional parameters file. Aborting!" << endl; return ILLEGAL_PARAMETERS; } - k_mer_length = ((String)additional_parameters.getValue("k_mer_length")).toInt(); + k_mer_length = String(additional_parameters.getValue("k_mer_length").toString()).toInt(); if (additional_parameters.getValue("sigma") == DataValue::EMPTY && svm.getIntParameter(SVMWrapper::KERNEL_TYPE) == SVMWrapper::OLIGO) { @@ -185,7 +185,7 @@ class TOPPPTPredict : cout << "No sigma saved in additional parameters file. Aborting!" << endl; return ILLEGAL_PARAMETERS; } - sigma = ((String)additional_parameters.getValue("sigma")).toFloat(); + sigma = String(additional_parameters.getValue("sigma").toString()).toFloat(); } String document_id; diff --git a/src/topp/PeakPickerHiRes.cpp b/src/topp/PeakPickerHiRes.cpp index c95fc98cff8..df832b4b0d5 100644 --- a/src/topp/PeakPickerHiRes.cpp +++ b/src/topp/PeakPickerHiRes.cpp @@ -136,7 +136,7 @@ class TOPPPeakPickerHiRes : PPHiResMzMLConsumer(String filename, const PeakPickerHiRes& pp) : MSDataWritingConsumer(std::move(filename)), - ms_levels_(pp.getParameters().getValue("ms_levels").toIntList()) + ms_levels_(pp.getParameters().getValue("ms_levels").toIntVector()) { pp_ = pp; } diff --git a/src/topp/ProteinQuantifier.cpp b/src/topp/ProteinQuantifier.cpp index 39c732eb744..d20fd8f426c 100644 --- a/src/topp/ProteinQuantifier.cpp +++ b/src/topp/ProteinQuantifier.cpp @@ -608,7 +608,7 @@ class TOPPProteinQuantifier : for (StringList::iterator it = relevant_params.begin(); it != relevant_params.end(); ++it) { - String value = algo_params_.getValue(*it); + String value = algo_params_.getValue(*it).toString(); if (value != "false") params += *it + "=" + value + ", "; } if (params.empty()) params = "(none)"; diff --git a/src/topp/QualityControl.cpp b/src/topp/QualityControl.cpp index 3f331ea941c..855fd137f59 100644 --- a/src/topp/QualityControl.cpp +++ b/src/topp/QualityControl.cpp @@ -165,7 +165,7 @@ class TOPPQualityControl : public TOPPBase vector contaminants; if (!in_contaminants.empty()) { - FASTAFile::load(in_contaminants, contaminants); + FASTAFile().load(in_contaminants, contaminants); status |= QCBase::Requires::CONTAMINANTS; } ConsensusMap cmap; @@ -254,6 +254,7 @@ class TOPPQualityControl : public TOPPBase // Loop through featuremaps... vector all_new_upep_ids; + vector tic_results; for (Size i = 0; i < number_exps; ++i) { //------------------------------------------------------------- @@ -337,7 +338,7 @@ class TOPPQualityControl : public TOPPBase if (qc_tic.isRunnable(status)) { - qc_tic.compute(exp); + tic_results.push_back(qc_tic.compute(exp)); } if (qc_ms2stats.isRunnable(status)) @@ -423,7 +424,7 @@ class TOPPQualityControl : public TOPPBase { MzTab mztab = MzTab::exportConsensusMapToMzTab(cmap, in_cm, true, true, true, true, "QC export from OpenMS"); MzTabMetaData meta = mztab.getMetaData(); - qc_tic.addMetaDataMetricsToMzTab(meta); + qc_tic.addMetaDataMetricsToMzTab(meta, tic_results); qc_ms2ir.addMetaDataMetricsToMzTab(meta); mztab.setMetaData(meta); diff --git a/src/topp/RTPredict.cpp b/src/topp/RTPredict.cpp index 5489f64ef7f..04025a45d55 100644 --- a/src/topp/RTPredict.cpp +++ b/src/topp/RTPredict.cpp @@ -305,7 +305,7 @@ class TOPPRTPredict : } if (additional_parameters.getValue("kernel_type") != DataValue::EMPTY) { - svm.setParameter(SVMWrapper::KERNEL_TYPE, ((String) additional_parameters.getValue("kernel_type")).toInt()); + svm.setParameter(SVMWrapper::KERNEL_TYPE, String(additional_parameters.getValue("kernel_type").toString()).toInt()); } if (additional_parameters.getValue("border_length") == DataValue::EMPTY @@ -315,7 +315,7 @@ class TOPPRTPredict : cout << "No border length saved in additional parameters file. Aborting!" << endl; return ILLEGAL_PARAMETERS; } - border_length = ((String)additional_parameters.getValue("border_length")).toInt(); + border_length = String(additional_parameters.getValue("border_length").toString()).toInt(); if (additional_parameters.getValue("k_mer_length") == DataValue::EMPTY && svm.getIntParameter(SVMWrapper::KERNEL_TYPE) == SVMWrapper::OLIGO) { @@ -323,7 +323,7 @@ class TOPPRTPredict : cout << "No k-mer length saved in additional parameters file. Aborting!" << endl; return ILLEGAL_PARAMETERS; } - k_mer_length = ((String)additional_parameters.getValue("k_mer_length")).toInt(); + k_mer_length = String(additional_parameters.getValue("k_mer_length").toString()).toInt(); if (additional_parameters.getValue("sigma") == DataValue::EMPTY && svm.getIntParameter(SVMWrapper::KERNEL_TYPE) == SVMWrapper::OLIGO) { @@ -331,7 +331,7 @@ class TOPPRTPredict : cout << "No sigma saved in additional parameters file. Aborting!" << endl; return ILLEGAL_PARAMETERS; } - sigma = ((String)additional_parameters.getValue("sigma")).toDouble(); + sigma = String(additional_parameters.getValue("sigma").toString()).toDouble(); if (!separation_prediction && additional_parameters.getValue("sigma_0") == DataValue::EMPTY) { writeLog_("No sigma_0 saved in additional parameters file. Aborting!"); diff --git a/src/topp/executables.cmake b/src/topp/executables.cmake index 4d9f599e5c9..d2fd8120ece 100644 --- a/src/topp/executables.cmake +++ b/src/topp/executables.cmake @@ -43,7 +43,6 @@ IDPosteriorErrorProbability IDRipper IDRTCalibration InclusionExclusionListCreator -InspectAdapter InternalCalibration IsobaricAnalyzer LuciphorAdapter diff --git a/src/utils/AccurateMassSearch.cpp b/src/utils/AccurateMassSearch.cpp index 3374dd16055..db3cced4ecd 100644 --- a/src/utils/AccurateMassSearch.cpp +++ b/src/utils/AccurateMassSearch.cpp @@ -106,13 +106,13 @@ class TOPPAccurateMassSearch : // move some params from algorithm section to top level (to support input file functionality) Param p = AccurateMassSearchEngine().getDefaults(); registerTOPPSubsection_("db", "Database files which contain the identifications"); - registerInputFileList_("db:mapping", "", p.getValue("db:mapping"), p.getDescription("db:mapping"), true, false, {"skipexists"}); + registerInputFileList_("db:mapping", "", ListUtils::toStringList(p.getValue("db:mapping")), p.getDescription("db:mapping"), true, false, {"skipexists"}); setValidFormats_("db:mapping", {"tsv"}); - registerInputFileList_("db:struct", "", p.getValue("db:struct"), p.getDescription("db:struct"), true, false, {"skipexists"}); + registerInputFileList_("db:struct", "", ListUtils::toStringList(p.getValue("db:struct")), p.getDescription("db:struct"), true, false, {"skipexists"}); setValidFormats_("db:struct", {"tsv"}); - registerInputFile_("positive_adducts", "", p.getValue("positive_adducts"), p.getDescription("positive_adducts"), true, false, {"skipexists"}); + registerInputFile_("positive_adducts", "", p.getValue("positive_adducts").toString(), p.getDescription("positive_adducts"), true, false, {"skipexists"}); setValidFormats_("positive_adducts", {"tsv"}); - registerInputFile_("negative_adducts", "", p.getValue("negative_adducts"), p.getDescription("negative_adducts"), true, false, {"skipexists"}); + registerInputFile_("negative_adducts", "", p.getValue("negative_adducts").toString(), p.getDescription("negative_adducts"), true, false, {"skipexists"}); setValidFormats_("negative_adducts", {"tsv"}); // addEmptyLine_(); // addText_("Parameters for the accurate mass search can be given in the 'algorithm' part of INI file."); @@ -141,8 +141,8 @@ class TOPPAccurateMassSearch : Param ams_param = getParam_().copy("algorithm:", true); // copy top-level params to algorithm - ams_param.setValue("db:mapping", getStringList_("db:mapping")); - ams_param.setValue("db:struct", getStringList_("db:struct")); + ams_param.setValue("db:mapping", ListUtils::create(getStringList_("db:mapping"))); + ams_param.setValue("db:struct", ListUtils::create(getStringList_("db:struct"))); ams_param.setValue("positive_adducts", getStringOption_("positive_adducts")); ams_param.setValue("negative_adducts", getStringOption_("negative_adducts")); diff --git a/src/utils/DecoyDatabase.cpp b/src/utils/DecoyDatabase.cpp index f92d5c35610..af4efa5e8e1 100644 --- a/src/utils/DecoyDatabase.cpp +++ b/src/utils/DecoyDatabase.cpp @@ -156,7 +156,7 @@ class TOPPDecoyDatabase : bool keepN = decoy_param.getValue("keepPeptideNTerm").toBool(); bool keepC = decoy_param.getValue("keepPeptideCTerm").toBool(); - String keep_const_pattern = decoy_param.getValue("non_shuffle_pattern"); + String keep_const_pattern = decoy_param.getValue("non_shuffle_pattern").toString(); Int max_attempts = getIntOption_("shuffle_max_attempts"); double identity_threshold = getDoubleOption_("shuffle_sequence_identity_threshold"); diff --git a/src/utils/INIUpdater.cpp b/src/utils/INIUpdater.cpp index 849c3dbb57d..2ccb05cc0e9 100644 --- a/src/utils/INIUpdater.cpp +++ b/src/utils/INIUpdater.cpp @@ -130,7 +130,7 @@ class TOPPINIUpdater : } else { - version = p.getValue("info:version"); + version = p.getValue("info:version").toString(); // TODO: return on newer version?! } @@ -162,11 +162,11 @@ class TOPPINIUpdater : break; } - String old_name = p.getValue(sec_inst + "tool_name"); + String old_name = p.getValue(sec_inst + "tool_name").toString(); String new_tool; String ttype; // find mapping to new tool (might be the same name) - if (p.exists(sec_inst + "tool_type")) ttype = p.getValue(sec_inst + "tool_type"); + if (p.exists(sec_inst + "tool_type")) ttype = p.getValue(sec_inst + "tool_type").toString(); if (!updater.getNewToolName(old_name, ttype, new_tool)) { String type_text = ((ttype == "") ? "" : " with type '" + ttype + "' "); @@ -279,7 +279,7 @@ class TOPPINIUpdater : } else { - version_old = p.getValue(sections[0] + ":version"); + version_old = p.getValue(sections[0] + ":version").toString(); // TODO: return on newer version?! } @@ -300,7 +300,7 @@ class TOPPINIUpdater : String new_tool; String ttype; // find mapping to new tool (might be the same name) - if (p.exists(sec_inst + "type")) ttype = p.getValue(sec_inst + "type"); + if (p.exists(sec_inst + "type")) ttype = p.getValue(sec_inst + "type").toString(); if (!updater.getNewToolName(sections[s], ttype, new_tool)) { String type_text = ((ttype == "") ? "" : " with type '" + ttype + "' "); diff --git a/src/utils/MSSimulator.cpp b/src/utils/MSSimulator.cpp index 262f25ee679..fb10212b957 100644 --- a/src/utils/MSSimulator.cpp +++ b/src/utils/MSSimulator.cpp @@ -170,9 +170,9 @@ class TOPPMSSimulator : // set parameters for the different types of random number generators // we support one for the technical and one for the biological variability tmp.setValue("RandomNumberGenerators:biological", "random", "Controls the 'biological' randomness of the generated data (e.g. systematic effects like deviations in RT). If set to 'random' each experiment will look different. If set to 'reproducible' each experiment will have the same outcome (given that the input data is the same)"); - tmp.setValidStrings("RandomNumberGenerators:biological", ListUtils::create("reproducible,random")); + tmp.setValidStrings("RandomNumberGenerators:biological", {"reproducible","random"}); tmp.setValue("RandomNumberGenerators:technical", "random", "Controls the 'technical' randomness of the generated data (e.g. noise in the raw signal). If set to 'random' each experiment will look different. If set to 'reproducible' each experiment will have the same outcome (given that the input data is the same)"); - tmp.setValidStrings("RandomNumberGenerators:technical", ListUtils::create("reproducible,random")); + tmp.setValidStrings("RandomNumberGenerators:technical", {"reproducible","random"}); tmp.setSectionDescription("RandomNumberGenerators", "Parameters for generating the random aspects (e.g. noise) in the simulated data. The generation is separated into two parts, the technical part, like noise in the raw signal, and the biological part, like systematic deviations in the predicted retention times"); return tmp; } diff --git a/src/utils/MetaProSIP.cpp b/src/utils/MetaProSIP.cpp index f055be4c549..beb14d9165f 100644 --- a/src/utils/MetaProSIP.cpp +++ b/src/utils/MetaProSIP.cpp @@ -2997,10 +2997,11 @@ class RIntegration bool cluster_flag = getFlag_("cluster"); // read descriptions from FASTA and create map for fast annotation - OPENMS_LOG_INFO << "loading sequences..." << endl; String in_fasta = getStringOption_("in_fasta"); vector fasta_entries; - FASTAFile::load(in_fasta, fasta_entries); + FASTAFile fasta_file; + fasta_file.setLogType(log_type_); + fasta_file.load(in_fasta, fasta_entries); map proteinid_to_description; for (vector::const_iterator it = fasta_entries.begin(); it != fasta_entries.end(); ++it) { diff --git a/src/utils/MultiplexResolver.cpp b/src/utils/MultiplexResolver.cpp index f990c327a21..34691bd201e 100644 --- a/src/utils/MultiplexResolver.cpp +++ b/src/utils/MultiplexResolver.cpp @@ -152,9 +152,9 @@ class TOPPMultiplexResolver : defaults.setValue("labels", "[][Lys8,Arg10]", "Labels used for labelling the samples. [...] specifies the labels for a single sample. For example\n\n[][Lys8,Arg10] ... SILAC\n[][Lys4,Arg6][Lys8,Arg10] ... triple-SILAC\n[Dimethyl0][Dimethyl6] ... Dimethyl\n[Dimethyl0][Dimethyl4][Dimethyl8] ... triple Dimethyl\n[ICPL0][ICPL4][ICPL6][ICPL10] ... ICPL"); defaults.setValue("missed_cleavages", 0, "Maximum number of missed cleavages due to incomplete digestion. (Only relevant if enzymatic cutting site coincides with labelling site. For example, Arg/Lys in the case of trypsin digestion and SILAC labelling.)"); defaults.setMinInt("missed_cleavages", 0); - defaults.setValue("mass_tolerance", 0.1, "Mass tolerance in Da for matching the mass shifts in the detected peptide multiplet to the theoretical mass shift pattern.", ListUtils::create("advanced")); - defaults.setValue("mz_tolerance", 10, "m/z tolerance in ppm for checking if dummy feature vicinity was blacklisted.", ListUtils::create("advanced")); - defaults.setValue("rt_tolerance", 5, "Retention time tolerance in seconds for checking if dummy feature vicinity was blacklisted.", ListUtils::create("advanced")); + defaults.setValue("mass_tolerance", 0.1, "Mass tolerance in Da for matching the mass shifts in the detected peptide multiplet to the theoretical mass shift pattern.", {"advanced"}); + defaults.setValue("mz_tolerance", 10, "m/z tolerance in ppm for checking if dummy feature vicinity was blacklisted.", {"advanced"}); + defaults.setValue("rt_tolerance", 5, "Retention time tolerance in seconds for checking if dummy feature vicinity was blacklisted.", {"advanced"}); } if (section == "labels") @@ -164,7 +164,7 @@ class TOPPMultiplexResolver : for (Param::ParamIterator it = p.begin(); it != p.end(); ++it) { - defaults.setValue(it->name, it->value, it->description, ListUtils::create("advanced")); + defaults.setValue(it->name, it->value, it->description, {"advanced"}); defaults.setMinFloat(it->name, 0.0); } } @@ -188,7 +188,7 @@ class TOPPMultiplexResolver : */ void getParameters_algorithm_() { - labels_ = getParam_().getValue("algorithm:labels"); + labels_ = getParam_().getValue("algorithm:labels").toString(); missed_cleavages_ = getParam_().getValue("algorithm:missed_cleavages"); mass_tolerance_ = getParam_().getValue("algorithm:mass_tolerance"); mz_tolerance_ = getParam_().getValue("algorithm:mz_tolerance"); diff --git a/src/utils/NovorAdapter.cpp b/src/utils/NovorAdapter.cpp index 7f5b6519c19..2471aee1afa 100644 --- a/src/utils/NovorAdapter.cpp +++ b/src/utils/NovorAdapter.cpp @@ -105,7 +105,7 @@ class TOPPNovorAdapter : { public: TOPPNovorAdapter() : - TOPPBase("NovorAdapter", "Template for Tool creation", false, + TOPPBase("NovorAdapter", "Performs de novo sequencing of peptides from MS/MS data with Novor.", false, { Citation{"Ma Bin", "Novor: Real-Time Peptide de Novo Sequencing Software", diff --git a/src/utils/NucleicAcidSearchEngine.cpp b/src/utils/NucleicAcidSearchEngine.cpp index 9a57ffbc37a..1a27e539f10 100644 --- a/src/utils/NucleicAcidSearchEngine.cpp +++ b/src/utils/NucleicAcidSearchEngine.cpp @@ -284,7 +284,7 @@ class NucleicAcidSearchEngine : { set modifications; auto db_ptr = RibonucleotideDB::getInstance(); - boost::regex double_digits("(\\d)(?=\\d)"); + boost::regex double_digits(R"((\d)(?=\d))"); for (String m : mod_names) { ConstRibonucleotidePtr mod = 0; diff --git a/src/utils/OpenSwathWorkflow.cpp b/src/utils/OpenSwathWorkflow.cpp index 4e472849730..dd6e6db486e 100644 --- a/src/utils/OpenSwathWorkflow.cpp +++ b/src/utils/OpenSwathWorkflow.cpp @@ -601,7 +601,7 @@ class TOPPOpenSwathWorkflow Param p; p.setValue("alignmentMethod", "linear", "How to perform the alignment to the normalized RT space using anchor points. 'linear': perform linear regression (for few anchor points). 'interpolated': Interpolate between anchor points (for few, noise-free anchor points). 'lowess' Use local regression (for many, noisy anchor points). 'b_spline' use b splines for smoothing."); - p.setValidStrings("alignmentMethod", ListUtils::create("linear,interpolated,lowess,b_spline")); + p.setValidStrings("alignmentMethod", {"linear","interpolated","lowess","b_spline"}); p.setValue("lowess:span", 0.05, "Span parameter for lowess"); p.setMinFloat("lowess:span", 0.0); p.setMaxFloat("lowess:span", 1.0); @@ -609,17 +609,17 @@ class TOPPOpenSwathWorkflow p.setMinInt("b_spline:num_nodes", 0); p.setValue("outlierMethod", "iter_residual", "Which outlier detection method to use (valid: 'iter_residual', 'iter_jackknife', 'ransac', 'none'). Iterative methods remove one outlier at a time. Jackknife approach optimizes for maximum r-squared improvement while 'iter_residual' removes the datapoint with the largest residual error (removal by residual is computationally cheaper, use this with lots of peptides)."); - p.setValidStrings("outlierMethod", ListUtils::create("iter_residual,iter_jackknife,ransac,none")); + p.setValidStrings("outlierMethod", {"iter_residual","iter_jackknife","ransac","none"}); p.setValue("useIterativeChauvenet", "false", "Whether to use Chauvenet's criterion when using iterative methods. This should be used if the algorithm removes too many datapoints but it may lead to true outliers being retained."); - p.setValidStrings("useIterativeChauvenet", ListUtils::create("true,false")); + p.setValidStrings("useIterativeChauvenet", {"true","false"}); p.setValue("RANSACMaxIterations", 1000, "Maximum iterations for the RANSAC outlier detection algorithm."); p.setValue("RANSACMaxPercentRTThreshold", 3, "Maximum threshold in RT dimension for the RANSAC outlier detection algorithm (in percent of the total gradient). Default is set to 3% which is around +/- 4 minutes on a 120 gradient."); p.setValue("RANSACSamplingSize", 10, "Sampling size of data points per iteration for the RANSAC outlier detection algorithm."); p.setValue("estimateBestPeptides", "false", "Whether the algorithms should try to choose the best peptides based on their peak shape for normalization. Use this option you do not expect all your peptides to be detected in a sample and too many 'bad' peptides enter the outlier removal step (e.g. due to them being endogenous peptides or using a less curated list of peptides)."); - p.setValidStrings("estimateBestPeptides", ListUtils::create("true,false")); + p.setValidStrings("estimateBestPeptides", {"true","false"}); p.setValue("InitialQualityCutoff", 0.5, "The initial overall quality cutoff for a peak to be scored (range ca. -2 to 2)"); p.setValue("OverallQualityCutoff", 5.5, "The overall quality cutoff for a peak to go into the retention time estimation (range ca. 0 to 10)"); @@ -854,8 +854,8 @@ class TOPPOpenSwathWorkflow /////////////////////////////////// // Get the transformation information (using iRT peptides) /////////////////////////////////// - String irt_trafo_out = debug_params.getValue("irt_trafo"); - String irt_mzml_out = debug_params.getValue("irt_mzml"); + String irt_trafo_out = debug_params.getValue("irt_trafo").toString(); + String irt_mzml_out = debug_params.getValue("irt_mzml").toString(); Param irt_detection_param = getParam_().copy("RTNormalization:", true); Param calibration_param = getParam_().copy("Calibration:", true); calibration_param.setValue("mz_extraction_window", cp_irt.mz_extraction_window); diff --git a/src/utils/ProteomicsLFQ.cpp b/src/utils/ProteomicsLFQ.cpp index 3952f7fc773..f8d6cb092d8 100644 --- a/src/utils/ProteomicsLFQ.cpp +++ b/src/utils/ProteomicsLFQ.cpp @@ -537,7 +537,7 @@ class ProteomicsLFQ : writeDebug_("Parameters passed to MapAlignmentAlgorithms", mat_param, 3); Param model_params = TOPPMapAlignerBase::getModelDefaults("b_spline"); - String model_type = model_params.getValue("type"); + String model_type = model_params.getValue("type").toString(); model_params = model_params.copy(model_type + ":", true); try diff --git a/src/utils/QCCalculator.cpp b/src/utils/QCCalculator.cpp index 1e9b006bd0d..646bd82767d 100644 --- a/src/utils/QCCalculator.cpp +++ b/src/utils/QCCalculator.cpp @@ -82,6 +82,7 @@ using namespace std; - @p address only for mzQC: contact address (mail/e-mail or phone) of the person creating the mzQC file - @p label only for mzQC: RECOMMENDED unique and informative label for the run, so that it can be used as a figure label - @p description only for mzQC: description and comments about the mzQC file contents + - @p out_type specifies the output file type, default: determined by output file extension Output is in mzQC with JSON formatting or qcML format (see parameter @p out) which can be viewed directly in a modern browser (chromium, firefox, safari). The output file specified by the user determines which output file format will be used. @@ -122,10 +123,12 @@ class TOPPQCCalculator : registerInputFile_("in", "", "", "raw data input file (this is relevant if you want to look at MS1, MS2 and precursor peak information)"); setValidFormats_("in", ListUtils::create("mzML")); registerOutputFile_("out", "", "", "Your QC file."); - setValidFormats_("out", ListUtils::create("mzQC,qcML")); + setValidFormats_("out", {"mzQC", "qcML"}); + registerStringOption_("out_type", "", "", "Output file type -- default: determined from file extension or content", false); + setValidStrings_("out_type", {"mzQC", "qcML"}); registerStringOption_("label", "